1// Copyright 2012 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// The race detector does not understand ParFor synchronization. 6// +build !race 7 8package runtime_test 9 10import ( 11 . "runtime" 12 "testing" 13 "unsafe" 14) 15 16var gdata []uint64 17 18// Simple serial sanity test for parallelfor. 19func TestParFor(t *testing.T) { 20 const P = 1 21 const N = 20 22 data := make([]uint64, N) 23 for i := uint64(0); i < N; i++ { 24 data[i] = i 25 } 26 desc := NewParFor(P) 27 // Avoid making func a closure: parfor cannot invoke them. 28 // Since it doesn't happen in the C code, it's not worth doing 29 // just for the test. 30 gdata = data 31 ParForSetup(desc, P, N, nil, true, func(desc *ParFor, i uint32) { 32 data := gdata 33 data[i] = data[i]*data[i] + 1 34 }) 35 ParForDo(desc) 36 for i := uint64(0); i < N; i++ { 37 if data[i] != i*i+1 { 38 t.Fatalf("Wrong element %d: %d", i, data[i]) 39 } 40 } 41} 42 43// Test that nonblocking parallelfor does not block. 44func TestParFor2(t *testing.T) { 45 const P = 7 46 const N = 1003 47 data := make([]uint64, N) 48 for i := uint64(0); i < N; i++ { 49 data[i] = i 50 } 51 desc := NewParFor(P) 52 ParForSetup(desc, P, N, (*byte)(unsafe.Pointer(&data)), false, func(desc *ParFor, i uint32) { 53 d := *(*[]uint64)(unsafe.Pointer(desc.Ctx)) 54 d[i] = d[i]*d[i] + 1 55 }) 56 for p := 0; p < P; p++ { 57 ParForDo(desc) 58 } 59 for i := uint64(0); i < N; i++ { 60 if data[i] != i*i+1 { 61 t.Fatalf("Wrong element %d: %d", i, data[i]) 62 } 63 } 64} 65 66// Test that iterations are properly distributed. 67func TestParForSetup(t *testing.T) { 68 const P = 11 69 const N = 101 70 desc := NewParFor(P) 71 for n := uint32(0); n < N; n++ { 72 for p := uint32(1); p <= P; p++ { 73 ParForSetup(desc, p, n, nil, true, func(desc *ParFor, i uint32) {}) 74 sum := uint32(0) 75 size0 := uint32(0) 76 end0 := uint32(0) 77 for i := uint32(0); i < p; i++ { 78 begin, end := ParForIters(desc, i) 79 size := end - begin 80 sum += size 81 if i == 0 { 82 size0 = size 83 if begin != 0 { 84 t.Fatalf("incorrect begin: %d (n=%d, p=%d)", begin, n, p) 85 } 86 } else { 87 if size != size0 && size != size0+1 { 88 t.Fatalf("incorrect size: %d/%d (n=%d, p=%d)", size, size0, n, p) 89 } 90 if begin != end0 { 91 t.Fatalf("incorrect begin/end: %d/%d (n=%d, p=%d)", begin, end0, n, p) 92 } 93 } 94 end0 = end 95 } 96 if sum != n { 97 t.Fatalf("incorrect sum: %d/%d (p=%d)", sum, n, p) 98 } 99 } 100 } 101} 102 103// Test parallel parallelfor. 104func TestParForParallel(t *testing.T) { 105 if GOARCH != "amd64" { 106 t.Log("temporarily disabled, see http://golang.org/issue/4155") 107 return 108 } 109 110 N := uint64(1e7) 111 if testing.Short() { 112 N /= 10 113 } 114 data := make([]uint64, N) 115 for i := uint64(0); i < N; i++ { 116 data[i] = i 117 } 118 P := GOMAXPROCS(-1) 119 c := make(chan bool, P) 120 desc := NewParFor(uint32(P)) 121 gdata = data 122 ParForSetup(desc, uint32(P), uint32(N), nil, false, func(desc *ParFor, i uint32) { 123 data := gdata 124 data[i] = data[i]*data[i] + 1 125 }) 126 for p := 1; p < P; p++ { 127 go func() { 128 ParForDo(desc) 129 c <- true 130 }() 131 } 132 ParForDo(desc) 133 for p := 1; p < P; p++ { 134 <-c 135 } 136 for i := uint64(0); i < N; i++ { 137 if data[i] != i*i+1 { 138 t.Fatalf("Wrong element %d: %d", i, data[i]) 139 } 140 } 141 142 data, desc = nil, nil 143 GC() 144} 145