11

Paul E. McKenney の Memory Barriers を読ん でいます。私は、すべてを無意味にし、何も理解していないと思わせる一文に出くわします。例を示しましょう

void foo(void)
{
   a = 1; #1
   b = 1; #2
}

void bar(void)
{
   while (b == 0) continue; #3
   assert(a == 1); #4
}

この 2 つの関数が異なるプロセッサで実行されているとします。ここで、最初のプロセッサが「a」へのストアをキューに格納し、b 命令のストアに進むため、2 番目のプロセッサによる b #2 へのストアの後に、a #1 へのストアが表示される可能性があります。OK、問題ありません。#1 と #2 の間の行に書き込みフェンスを追加しますが、このコードはまだ失敗する可能性があります。これは、2 番目のプロセッサが無効化メッセージをキューに入れる可能性があるためです。 #4 と #4 の間の線。

void foo(void)
{
   a = 1; #1
   write_memory_barrier();
   b = 1; #2
}

void bar(void)
{
   while (b == 0) continue; #3
   read_memory_barrier();
   assert(a == 1); #4
}

これにより、2 番目のプロセッサがキューに入れられたすべてのメッセージを処理し (a を無効化)、#4 の最初のプロセッサに read MESI メッセージを送信して再度読み取るようになります。わかった。次に記事は言う

そのため、多くの CPU アーキテクチャは、これら 2 つのいずれか一方のみを実行する、より弱いメモリ バリア命令を提供します。大まかに言えば、「読み取りメモリ バリア」は無効キューのみをマークし、「書き込みメモリ バリア」はストア バッファのみをマークします。本格的なメモリバリアは両方を行います。

素晴らしい、それは明らかですが、その後、私はこれを見ます

この結果、読み取りメモリ バリアは、それを実行する CPU でのみロードを命令するため、読み取りメモリ バリアに先行するすべてのロードは、読み取りメモリ バリアに続くすべてのロードの前に完了したように見えます。同様に、書き込みメモリ バリアは、書き込みメモリ バリアの前にあるすべてのストアが、書き込みメモリ バリアに続くストアの前に完了したように見えるように、ストアを実行する CPU でのみストアを注文します。

それで

読み取りメモリ バリアに先行するすべてのロードは、読み取りメモリ バリアに続くすべてのロードの前に完了したように見えます。

それは、前に説明したことすべてを混同します。どういう意味ですか?"a" #4 のロードの前に、関数 "bar" のどのロードを完了する必要がありますか? オブジェクト「a」が配置されているキャッシュラインを無効にすることができなかったため、プロセッサが古い値を読み取る可能性があるという理由だけで、この関数のメモリバリアなしでアサートが失敗する可能性があることを理解しています。

詳細な説明は本当に役に立ちます。私は一日中理解しようとしています。

よろしくお願いします。

4

1 に答える 1

10

どういう意味ですか?

これは、次の場合を意味します。

read
read
read
READ BARRIER
read
read
read

次に、読み取りバリアは、これらの読み取りを 2 つのバッチに分割する「結合点」として機能します。読み取りバリアに先行するすべての読み取りは、読み取りバリアに続く読み取りが開始される前に行われます。

(#4) のロードが開始される前に、どのロードをbar()完了する必要がありますか?a

(#3)のすべての読み取りbは、(#4) の読み取りの前に強制されaます。これは、a後まで読み取られないbことを意味します。これfoo()は、書き込みバリアを使用して、変更される (#2)aまでに既に1(#1)に変更されていることを確認するためbです。このように、2 つのバリアが連携して、assert ステートメントが常に成功するようにします。

于 2010-10-22T18:20:51.540 に答える