2016-03-18 24 views
2

Goで並行して相関を計算することに興味があります。私が持っている主な問題は、すべてのGoプロセスがまったく同じ計算を実行しているようだということです。私はここで非常に簡単な例で問題を再現しました。 私が取得:並列処理で配列を処理すると、予期しない結果が発生する

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

代わりに:私は上に移動した場合

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

「をwg.Wait()」私は良い結果を得るませんが、何の並列処理:( 感謝の事前にあなたのコメントのための!

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 

    } 
+3

FAQ:https://golang.org/doc/faq#closures_and_goroutines、実質的に、あなたはあなたのゴルーチンを与えたい – JimB

+0

注意より大きいタスク(例えば、N個のCPUを持っている場合は、それぞれの1/nに与えます)。 1つの追加は非常に高速で、スレッドを起動するような調整などはログになります。 – twotwotwo

答えて

3

すべてのゴルーチンにiの同じコピーにアクセスしている。ループは、外出先のいずれかの前に終了することが起こるので、あなたが見出力されていますルーチンは実行を開始します。

これは、iがすべてのゴルーチンで同じ値を持つこと、つまり、ループ内に最後の値があることを意味します。

それぞれのゴルーチンに引数としてiを渡すことで、代わりにゴルーチンごとにコピーを操作して、この問題を解決します。

wg.Wait()をループに追加したときに期待した結果が得られた理由は、次に同期を開始してから、次のものを開始するまでゴルーチンが終了するのを待っているからです。つまり、実行は実際にはパラレルではなくシリアルであったことを意味します。ここで

は、あなたが期待通りに動作更新されたコード、です:

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 

} 
+0

または一般的な「i:= i」idom:http://play.golang.org/p/Zcof5HLrQr – JimB

+0

はい、それも機能します。私はこの方法をより明確に見出します。 –

+0

うわー!印象的なソリューション、シンプルだが見つけるのは難しい!ありがとう! – Fred

関連する問題