10

preshing のブログMemory Reordering Caught in the Actを読んでいて、彼のサンプル コードでメモリの再配列を再現しました。

では、メモリの並び替えを Go で再現できないかと思い、go でサンプルコードを書きましたが、メモリの並び替えは Go では表示されません。

いくつかの調査結果を共有するために書いています。

また、Go がメモリの並べ替えを取得できなかった理由を説明していただけますか? ありがとう。

Go でのコード例:

 package main

    import (
            "fmt"
            "math/rand"
    )

    var x, y, r1, r2 int
    var detected = 0

    func randWait() {
            for rand.Intn(8) != 0 {
            }
    }

    func main() {
            beginSig1 := make(chan bool, 1)
            beginSig2 := make(chan bool, 1)
            endSig1 := make(chan bool, 1)
            endSig2 := make(chan bool, 1)
            go func() {
                    for {
                            <-beginSig1
                            randWait()
                            x = 1
                            r1 = y
                            endSig1 <- true
                    }
            }()
            go func() {
                    for {
                            <-beginSig2
                            randWait()
                            y = 1
                            r2 = x
                            endSig2 <- true
                    }
            }()
            for i := 1; ; i = i + 1 {
                    x = 0
                    y = 0
                    beginSig1 <- true
                    beginSig2 <- true
                    <-endSig1
                    <-endSig2
                    if r1 == 0 && r2 == 0 {
                            detected = detected + 1
                            fmt.Println(detected, "reorders detected after ", i, "iterations")
                    }
            }
    } 

アセンブリ コード (「ndisasm -b 32」による) は、C++ と Go の間で異なることを示しています

  • C++ からのアセンブリ コード

    00000CF0  C705520300000100  mov dword [0x352],0x1     //X=1
             -0000
    00000CFA  8B0550030000      mov eax,[0x350]     
    00000D00  89054E030000      mov [0x34e],eax      //r1=Y
    
  • Go からのアセンブリ コード

    000013EA  48                dec eax
    000013EB  C70425787F170001  mov dword [0x177f78],0x1     //x=1
             -000000
    000013F6  48                dec eax
    000013F7  8B1C25807F1700    mov ebx,[0x177f80]
    000013FE  48                dec eax
    000013FF  891C25687F1700    mov [0x177f68],ebx          //r1=Y
    00001406  48                dec eax
    

Goは共有メモリの周りのアクセスを使用しているようですが、メモリの並べ替えを防ぐことができるdec eax意味がありませんdec eax

  1. Intel® 64 and IA-32 Architectures Software Developer Manuals Volume 3、セクション 8.2 には、メモリの並べ替えを妨げる可能性のあるケースが示されdec eaxていますが、含まれていません...

  2. dec eaxCコードで共有メモリアクセスのマージンとして追加しようとしましたが、メモリの並べ替えがまだ残っています。

今のところ、その理由についての手がかりはありません。助けてください、ありがとう。

4

3 に答える 3

8

GOMAXPROC を設定する呼び出しがどこにもありません。呼び出さないと、再注文が表示されない 1 つの CPU だけで実行されます: http://golang.org/pkg/runtime/#GOMAXPROCS

更新: Go 1.5 (2015/08/19 リリース) 以降では、GOMAXPROCS を設定する必要がなくなりました - Go はデフォルトですべての CPU を使用します。

于 2013-11-11T11:20:04.783 に答える
0

Go メモリ モデルは、C や C++ のメモリ モデルではありません。

http://golang.org/ref/memを見てください。「前に発生する」HB 関係と、それがチャネルにどのように関係しているかが説明されています。現在の実装では、メモリ モデルで必要とされるよりも多くの HB が含まれている可能性があることに注意してください。

于 2013-11-11T08:27:32.667 に答える