github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/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  }