parfor_test.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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. // The race detector does not understand ParFor synchronization.
  5. // +build !race
  6. package runtime_test
  7. import (
  8. . "runtime"
  9. "testing"
  10. "unsafe"
  11. )
  12. var gdata []uint64
  13. // Simple serial sanity test for parallelfor.
  14. func TestParFor(t *testing.T) {
  15. const P = 1
  16. const N = 20
  17. data := make([]uint64, N)
  18. for i := uint64(0); i < N; i++ {
  19. data[i] = i
  20. }
  21. desc := NewParFor(P)
  22. // Avoid making func a closure: parfor cannot invoke them.
  23. // Since it doesn't happen in the C code, it's not worth doing
  24. // just for the test.
  25. gdata = data
  26. ParForSetup(desc, P, N, nil, true, func(desc *ParFor, i uint32) {
  27. data := gdata
  28. data[i] = data[i]*data[i] + 1
  29. })
  30. ParForDo(desc)
  31. for i := uint64(0); i < N; i++ {
  32. if data[i] != i*i+1 {
  33. t.Fatalf("Wrong element %d: %d", i, data[i])
  34. }
  35. }
  36. }
  37. // Test that nonblocking parallelfor does not block.
  38. func TestParFor2(t *testing.T) {
  39. const P = 7
  40. const N = 1003
  41. data := make([]uint64, N)
  42. for i := uint64(0); i < N; i++ {
  43. data[i] = i
  44. }
  45. desc := NewParFor(P)
  46. ParForSetup(desc, P, N, (*byte)(unsafe.Pointer(&data)), false, func(desc *ParFor, i uint32) {
  47. d := *(*[]uint64)(unsafe.Pointer(desc.Ctx))
  48. d[i] = d[i]*d[i] + 1
  49. })
  50. for p := 0; p < P; p++ {
  51. ParForDo(desc)
  52. }
  53. for i := uint64(0); i < N; i++ {
  54. if data[i] != i*i+1 {
  55. t.Fatalf("Wrong element %d: %d", i, data[i])
  56. }
  57. }
  58. }
  59. // Test that iterations are properly distributed.
  60. func 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. // Test parallel parallelfor.
  96. func TestParForParallel(t *testing.T) {
  97. N := uint64(1e7)
  98. if testing.Short() {
  99. N /= 10
  100. }
  101. data := make([]uint64, N)
  102. for i := uint64(0); i < N; i++ {
  103. data[i] = i
  104. }
  105. P := GOMAXPROCS(-1)
  106. c := make(chan bool, P)
  107. desc := NewParFor(uint32(P))
  108. gdata = data
  109. ParForSetup(desc, uint32(P), uint32(N), nil, false, func(desc *ParFor, i uint32) {
  110. data := gdata
  111. data[i] = data[i]*data[i] + 1
  112. })
  113. for p := 1; p < P; p++ {
  114. go func() {
  115. ParForDo(desc)
  116. c <- true
  117. }()
  118. }
  119. ParForDo(desc)
  120. for p := 1; p < P; p++ {
  121. <-c
  122. }
  123. for i := uint64(0); i < N; i++ {
  124. if data[i] != i*i+1 {
  125. t.Fatalf("Wrong element %d: %d", i, data[i])
  126. }
  127. }
  128. data, desc = nil, nil
  129. GC()
  130. }