【问题标题】:Processing arrays in Go parallel gives unexpected results并行处理数组会产生意想不到的结果
【发布时间】:2016-03-18 19:20:49
【问题描述】:

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

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

而不是:

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

如果我向上移动“wg.Wait()”,我会得到很好的结果,但没有并行性:( 提前感谢您的 cmets!

   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

    }

【问题讨论】:

  • 请注意,实际上,你想给你的 goroutines 更大的任务(例如,如果你有 N 个 cpus,给每个 1/n 做)。一个添加非常快,启动线程等的协调需要登录器。

标签: arrays go parallel-processing


【解决方案1】:

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

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

i 作为参数传递给每个 goroutine,从而对每个 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; 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

}

【讨论】:

  • 哇!令人印象深刻的解决方案,简单但很难找到!谢谢!
猜你喜欢
  • 2021-03-10
  • 2015-02-12
  • 1970-01-01
  • 2019-04-05
  • 1970-01-01
  • 2017-05-02
  • 1970-01-01
  • 2015-03-16
  • 1970-01-01
相关资源
最近更新 更多