Home | History | Annotate | Download | only in runtime
      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