在Go parallel中处理数组会产生意想不到的结果 [英] Processing arrays in Go parallel gives unexpected results

查看:86
本文介绍了在Go parallel中处理数组会产生意想不到的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有兴趣在Go中并行计算相关性。我所遇到的主要问题是所有Go流程似乎都执行完全相同的计算。我用一个非常简单的例子在这里再现了这个问题。
我得到:

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

而不是:

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

如果我向上移动wg.Wait(),我会得到好的结果,但不会产生并行性:(
提前感谢您的意见!

 包主

导入(
fmt
运行时
同步


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 (a1 [i],+,a2 [i],=,x)
}()
//wg.Wait()给出好结果
//但它不是并行处理
// 1 + 20 = 21
// 2 + 30 = 32
// 3 + 40 = 43
}
wg.Wait()//给出相同结果的重复:
// 4 + 50 = 54
// 4 + 50 = 54
/ / 4 + 50 = 54

}


解决方案

您正在访问所有goroutine中的 i 相同的副本。你看到的输出是因为循环恰好在任何goroutine开始执行之前完成。

这意味着 i 在所有goroutine中具有相同的值,即它在循环中的最后一个值。

将每个goroutine的 i 作为参数传递给每个goroutine,从而解决这个问题问题。

当您在循环中添加 wg.Wait()时,您看到您期望的结果的原因是因为你之后引入了同步,等待goroutine完成后再开始下一个。这意味着执行实际上是连续的,而不是平行的。



以下是更新后的代码,其效果如您所料:

  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;我< 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()好结果
//但它不是并行处理
// 1 + 20 = 21
// 2 + 30 = 32
// 3 + 40 = 43
}
wg.Wait()//给出相同结果的重复:
// 4 + 50 = 54
// 4 + 50 = 54
// 4 + 50 = 54

}


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

    }

解决方案

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

}

这篇关于在Go parallel中处理数组会产生意想不到的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆