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