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 ) 14 15 // Simple serial sanity test for parallelfor. 16 func TestParFor(t *testing.T) { 17 const P = 1 18 const N = 20 19 data := make([]uint64, N) 20 for i := uint64(0); i < N; i++ { 21 data[i] = i 22 } 23 desc := NewParFor(P) 24 ParForSetup(desc, P, N, true, func(desc *ParFor, i uint32) { 25 data[i] = data[i]*data[i] + 1 26 }) 27 ParForDo(desc) 28 for i := uint64(0); i < N; i++ { 29 if data[i] != i*i+1 { 30 t.Fatalf("Wrong element %d: %d", i, data[i]) 31 } 32 } 33 } 34 35 // Test that nonblocking parallelfor does not block. 36 func TestParFor2(t *testing.T) { 37 const P = 7 38 const N = 1003 39 data := make([]uint64, N) 40 for i := uint64(0); i < N; i++ { 41 data[i] = i 42 } 43 desc := NewParFor(P) 44 ParForSetup(desc, P, N, false, func(desc *ParFor, i uint32) { 45 data[i] = data[i]*data[i] + 1 46 }) 47 for p := 0; p < P; p++ { 48 ParForDo(desc) 49 } 50 for i := uint64(0); i < N; i++ { 51 if data[i] != i*i+1 { 52 t.Fatalf("Wrong element %d: %d", i, data[i]) 53 } 54 } 55 } 56 57 // Test that iterations are properly distributed. 58 func TestParForSetup(t *testing.T) { 59 const P = 11 60 const N = 101 61 desc := NewParFor(P) 62 for n := uint32(0); n < N; n++ { 63 for p := uint32(1); p <= P; p++ { 64 ParForSetup(desc, p, n, true, func(desc *ParFor, i uint32) {}) 65 sum := uint32(0) 66 size0 := uint32(0) 67 end0 := uint32(0) 68 for i := uint32(0); i < p; i++ { 69 begin, end := ParForIters(desc, i) 70 size := end - begin 71 sum += size 72 if i == 0 { 73 size0 = size 74 if begin != 0 { 75 t.Fatalf("incorrect begin: %d (n=%d, p=%d)", begin, n, p) 76 } 77 } else { 78 if size != size0 && size != size0+1 { 79 t.Fatalf("incorrect size: %d/%d (n=%d, p=%d)", size, size0, n, p) 80 } 81 if begin != end0 { 82 t.Fatalf("incorrect begin/end: %d/%d (n=%d, p=%d)", begin, end0, n, p) 83 } 84 } 85 end0 = end 86 } 87 if sum != n { 88 t.Fatalf("incorrect sum: %d/%d (p=%d)", sum, n, p) 89 } 90 } 91 } 92 } 93 94 // Test parallel parallelfor. 95 func TestParForParallel(t *testing.T) { 96 N := uint64(1e7) 97 if testing.Short() { 98 N /= 10 99 } 100 data := make([]uint64, N) 101 for i := uint64(0); i < N; i++ { 102 data[i] = i 103 } 104 P := GOMAXPROCS(-1) 105 c := make(chan bool, P) 106 desc := NewParFor(uint32(P)) 107 ParForSetup(desc, uint32(P), uint32(N), false, func(desc *ParFor, i uint32) { 108 data[i] = data[i]*data[i] + 1 109 }) 110 for p := 1; p < P; p++ { 111 go func() { 112 ParForDo(desc) 113 c <- true 114 }() 115 } 116 ParForDo(desc) 117 for p := 1; p < P; p++ { 118 <-c 119 } 120 for i := uint64(0); i < N; i++ { 121 if data[i] != i*i+1 { 122 t.Fatalf("Wrong element %d: %d", i, data[i]) 123 } 124 } 125 126 data, desc = nil, nil 127 GC() 128 } 129