diff options
author | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
---|---|---|
committer | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
commit | f154da9e12608589e8d5f0508f908a0c3e88a1bb (patch) | |
tree | f8255d51e10c6f1e0ed69702200b966c9556a431 /src/runtime/parfor_test.go | |
parent | 8d8329ed5dfb9622c82a9fbec6fd99a580f9c9f6 (diff) | |
download | golang-upstream/1.4.tar.gz |
Imported Upstream version 1.4upstream/1.4
Diffstat (limited to 'src/runtime/parfor_test.go')
-rw-r--r-- | src/runtime/parfor_test.go | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/src/runtime/parfor_test.go b/src/runtime/parfor_test.go new file mode 100644 index 000000000..de64285b8 --- /dev/null +++ b/src/runtime/parfor_test.go @@ -0,0 +1,139 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// The race detector does not understand ParFor synchronization. +// +build !race + +package runtime_test + +import ( + . "runtime" + "testing" + "unsafe" +) + +var gdata []uint64 + +// Simple serial sanity test for parallelfor. +func TestParFor(t *testing.T) { + const P = 1 + const N = 20 + data := make([]uint64, N) + for i := uint64(0); i < N; i++ { + data[i] = i + } + desc := NewParFor(P) + // Avoid making func a closure: parfor cannot invoke them. + // Since it doesn't happen in the C code, it's not worth doing + // just for the test. + gdata = data + ParForSetup(desc, P, N, nil, true, func(desc *ParFor, i uint32) { + data := gdata + data[i] = data[i]*data[i] + 1 + }) + ParForDo(desc) + for i := uint64(0); i < N; i++ { + if data[i] != i*i+1 { + t.Fatalf("Wrong element %d: %d", i, data[i]) + } + } +} + +// Test that nonblocking parallelfor does not block. +func TestParFor2(t *testing.T) { + const P = 7 + const N = 1003 + data := make([]uint64, N) + for i := uint64(0); i < N; i++ { + data[i] = i + } + desc := NewParFor(P) + ParForSetup(desc, P, N, (*byte)(unsafe.Pointer(&data)), false, func(desc *ParFor, i uint32) { + d := *(*[]uint64)(unsafe.Pointer(desc.Ctx)) + d[i] = d[i]*d[i] + 1 + }) + for p := 0; p < P; p++ { + ParForDo(desc) + } + for i := uint64(0); i < N; i++ { + if data[i] != i*i+1 { + t.Fatalf("Wrong element %d: %d", i, data[i]) + } + } +} + +// Test that iterations are properly distributed. +func TestParForSetup(t *testing.T) { + const P = 11 + const N = 101 + desc := NewParFor(P) + for n := uint32(0); n < N; n++ { + for p := uint32(1); p <= P; p++ { + ParForSetup(desc, p, n, nil, true, func(desc *ParFor, i uint32) {}) + sum := uint32(0) + size0 := uint32(0) + end0 := uint32(0) + for i := uint32(0); i < p; i++ { + begin, end := ParForIters(desc, i) + size := end - begin + sum += size + if i == 0 { + size0 = size + if begin != 0 { + t.Fatalf("incorrect begin: %d (n=%d, p=%d)", begin, n, p) + } + } else { + if size != size0 && size != size0+1 { + t.Fatalf("incorrect size: %d/%d (n=%d, p=%d)", size, size0, n, p) + } + if begin != end0 { + t.Fatalf("incorrect begin/end: %d/%d (n=%d, p=%d)", begin, end0, n, p) + } + } + end0 = end + } + if sum != n { + t.Fatalf("incorrect sum: %d/%d (p=%d)", sum, n, p) + } + } + } +} + +// Test parallel parallelfor. +func TestParForParallel(t *testing.T) { + N := uint64(1e7) + if testing.Short() { + N /= 10 + } + data := make([]uint64, N) + for i := uint64(0); i < N; i++ { + data[i] = i + } + P := GOMAXPROCS(-1) + c := make(chan bool, P) + desc := NewParFor(uint32(P)) + gdata = data + ParForSetup(desc, uint32(P), uint32(N), nil, false, func(desc *ParFor, i uint32) { + data := gdata + data[i] = data[i]*data[i] + 1 + }) + for p := 1; p < P; p++ { + go func() { + ParForDo(desc) + c <- true + }() + } + ParForDo(desc) + for p := 1; p < P; p++ { + <-c + } + for i := uint64(0); i < N; i++ { + if data[i] != i*i+1 { + t.Fatalf("Wrong element %d: %d", i, data[i]) + } + } + + data, desc = nil, nil + GC() +} |