github.com/hbdrawn/golang@v0.0.0-20141214014649-6b835209aba2/src/runtime/parfor_test.go (about) 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 8 package runtime_test 9 10 import ( 11 . "runtime" 12 "testing" 13 "unsafe" 14 ) 15 16 var gdata []uint64 17 18 // Simple serial sanity test for parallelfor. 19 func 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. 44 func 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. 67 func 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. 104 func TestParForParallel(t *testing.T) { 105 N := uint64(1e7) 106 if testing.Short() { 107 N /= 10 108 } 109 data := make([]uint64, N) 110 for i := uint64(0); i < N; i++ { 111 data[i] = i 112 } 113 P := GOMAXPROCS(-1) 114 c := make(chan bool, P) 115 desc := NewParFor(uint32(P)) 116 gdata = data 117 ParForSetup(desc, uint32(P), uint32(N), nil, false, func(desc *ParFor, i uint32) { 118 data := gdata 119 data[i] = data[i]*data[i] + 1 120 }) 121 for p := 1; p < P; p++ { 122 go func() { 123 ParForDo(desc) 124 c <- true 125 }() 126 } 127 ParForDo(desc) 128 for p := 1; p < P; p++ { 129 <-c 130 } 131 for i := uint64(0); i < N; i++ { 132 if data[i] != i*i+1 { 133 t.Fatalf("Wrong element %d: %d", i, data[i]) 134 } 135 } 136 137 data, desc = nil, nil 138 GC() 139 }