Processing arrays in Go parallel gives unexpected results

匿名 (未验证) 提交于 2019-12-03 01:04:01

问题:

I am interested to calculate correlations in parallel in Go. The main problem I have is that all the Go processes seems to execute exactly the same calculation. I reproduced here the problem with a very simple example. I obtain :

 4 + 50 = 54   4 + 50 = 54   4 + 50 = 54 

instead of :

 1 + 20 = 21   2 + 30 = 32   3 + 40 = 43 

If I move up "wg.Wait()" I obtain the good result but no parallelism :( Thank's in advance for your comments !

   package main      import (         "fmt"         "runtime"         "sync"     )      func process_array(x, y int) int {       r := x + y       return r     }       func main() {         a1 := []int{0, 1, 2, 3, 4}         a2 := []int{10, 20, 30, 40, 50}          runtime.GOMAXPROCS(8)         var wg sync.WaitGroup          for i := 1; i < 4 ; i++ {             wg.Add(1)             go func() {                 defer wg.Done()                 x :=process_array(a1[i],a2[i])                 fmt.Println(a1[i],"+", a2[i],"=", x)             }()             //wg.Wait() give the good result                          //but it is not parallel processing                         // 1 + 20 = 21                         // 2 + 30 = 32                         // 3 + 40 = 43           }         wg.Wait() // give a repetition of the same result :                   // 4 + 50 = 54                   // 4 + 50 = 54                   // 4 + 50 = 54      }

回答1:

You're accessing the same copy of i in all goroutines. The output you see is because the loop happens to finish before any of the goroutines start executing.

This means that i has the same value in all goroutines, i.e. the last value it had in the loop.

Passing i as an argument to each of your goroutines, thereby operating on a copy per goroutine instead, solves this problem.

The reason you saw the result you expected when you added wg.Wait() in the loop is because you then introduced synchronization, waiting for the goroutine to finish before starting the next one. That means the execution was in fact serial, not parallell.

Here's the updated code, which works as you'd expect:

package main  import (     "fmt"     "runtime"     "sync" )  func process_array(x, y int) int {     r := x + y     return r }  func main() {     a1 := []int{0, 1, 2, 3, 4}     a2 := []int{10, 20, 30, 40, 50}      runtime.GOMAXPROCS(8)     var wg sync.WaitGroup      for i := 1; i < 4; i++ {         wg.Add(1)         go func(i int) {             defer wg.Done()             x := process_array(a1[i], a2[i])             fmt.Println(a1[i], "+", a2[i], "=", x)         }(i)         //wg.Wait() give the good result         //but it is not parallel processing         // 1 + 20 = 21         // 2 + 30 = 32         // 3 + 40 = 43     }     wg.Wait() // give a repetition of the same result :     // 4 + 50 = 54     // 4 + 50 = 54     // 4 + 50 = 54  }


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!