rsc.io/go@v0.0.0-20150416155037-e040fd465409/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  )
    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  }