2017-02-17 12 views
0

私は2つのコードを持ち、私のデスクトップには32のコアがあります。アトミック操作が別々のスレッドを使用する方が速いのはなぜですか?

コードAは、32個のスレッドを使用し、以下のことを行い、

1)は、メモリ 2でいくつかのランダムな位置に値を書き込む)アトミックグローバル変数に値を追加します。

コードBは16スレッドを使用してランダムな場所に値を書き込み、別の16スレッドを使用してグローバル変数に値をアトミックに追加します。

コードBは、グローバル変数に対して1秒間に実行されるアトミック操作の数がより速いのはなぜかと思いました。ここで

は、コードはここ

var a uint64 = 0 

const N = 10 * 1024 * 1024 

var data [N]uint64 

func main() { 

    for i := 0; i < 32; i ++ { 
     go func(id int) { 
      source := rand.NewSource(int64(id)) 
      local_rand := rand.New(source) 
      for { 
       atomic.AddUint64(&a, uint64(1)) 
       data[local_rand.Int31n(N)] = uint64(1) 
      } 
     }(i) 

    } 

    var b uint64 = 0 

    for { 
     c := atomic.LoadUint64(&a) 

     fmt.Println(c - b) 
     b = c 
     time.Sleep(time.Second) 
    } 

} 

あるコードBはアトミック操作は高価である

var a uint64 = 0 

const N = 10 * 1024 * 1024 

var data [N]uint64 

func main() { 

    for i := 0; i < 16; i ++ { 
     go func(id int) { 
      source := rand.NewSource(int64(id)) 
      local_rand := rand.New(source) 
      for { 
       data[local_rand.Int31n(N)] = uint64(1) 
      } 
     }(i) 

    } 
    for i := 0; i < 16; i++ { 

     go func() { 
      for { 
       atomic.AddUint64(&a, uint64(1)) 
      } 

     }() 
    } 
    var b uint64 = 0 

    for { 
     c := atomic.LoadUint64(&a) 

     fmt.Println(c - b) 
     b = c 
     time.Sleep(time.Second) 
    } 

} 

答えて

1

です。アトミック性を維持するには、そのコードブロックに対して相互に排他的な実行を保証する必要があります。通常、これはロードリンク、ストア条件付きなどの命令を使用して実現されます。コードAでは32個のアトミック演算がありますが、コードBでは16個しか得られません。

実験として、コードAのメモリ操作でアトミック操作の順序を変更してみてください(最初にアトミックとアトミックを行ってください)。実行時間が短縮されるはずです。

+0

コードAのスレッド数を16に変更すると、パフォーマンスが向上するとは思われません。 – luyi0619

+0

私はあなたが提案したものと差異は見ません。まずアトミックを思い出します。私は何かが欠けていたか? – luyi0619

+0

すべてのスレッドが最初に原子力を尽くしている場合、それらはすべてロックのために競合します。最初にメモリを持っていれば、それらはすべて最初にメモリを行いますが、キャッシュされているかどうかによって、メモリの動作は異なるタイミングで完了します。これは、原子操作が異なる時に始まることを意味します。だから、あなたが以前に持っていたのと同じ競争相手を持つことはありません。だから私は実行時間が短くなることを期待していた。あなたのデータがすべてキャッシュされていて、私が期待していたことをしていないかもしれません。とにかく私の考えを超えた理論です。 –

関連する問題