3

intel のプロセッサ マニュアル:セクション 8.2.3.4 のリンクでは、ロードは以前のストアを別の場所に並べ替えることができるが、以前のストアを同じ場所に並べ替えることができないと記載されています。

したがって、次の 2 つの操作を並べ替えることができることを理解しています。

x = 1;
y = z;

また、次の 2 つの操作は順序を変更できません。

x = 1;
y = x;

しかし、ストアとロードが別の場所にある場合、ロードはストアを完全に取り囲んでいます。たとえば、次のようになります。

typedef union {
  uint64_t shared_var;
  uint32_t individual_var[2];
} my_union_t;

my_union_t var;
var.shared_var = 0;

var.individual_var[1] = 1;
int y = var.shared_var;

では、この場合の 'y' は 0 にできますか?

編集(@Hans Passant) 状況をさらに説明するために、この手法を使用して、ロックされた命令を使用せずにスレッド間の一種の準同期を考案できるかどうかを確認しようとしています。

したがって、グローバル変数が与えられた場合のより具体的な質問は次のとおりです。

my_union_t var;
var.shared_var = 0;

そして、次のコードを実行する 2 つのスレッド:

スレッド 1:

var.individual_var[0] = 1;
int y = __builtin_popcountl(var.shared_var);

スレッド 2:

var.individual_var[1] = 1;
int y = __builtin_popcountl(var.shared_var);

両方のスレッドで 'y' を 1 にすることはできますか?

注: __builtin_popcountl は、変数に設定されたビット数をカウントする組み込みの gcc 組み込み関数です。

4

2 に答える 2

1

最後で最も重要な質問1 :

そして、次のコードを実行する 2 つのスレッド:

スレッド 1:

var.individual_var[0] = 1;
int y = __builtin_popcountl(var.shared_var);

スレッド 2:

var.individual_var[1] = 1;
int y = __builtin_popcountl(var.shared_var);

両方のスレッドで 'y' を 1 にすることはできますか?

はい、できますが、重複する読み取りは SDM でカバーされていないため、チップが実際にこれを行うかどうかは、テストしないとわかりません。

このケースは基本的に、8.2.3.4 (ストア バッファリング) と 8.2.3.5 (ストア フォワーディング) のケースの組み合わせです。結果の一部は現在のローカル ストアから取得され、残りの結果はグローバルに表示されるストア (つまり、「メモリ」) から取得される必要があります。

1CPUは両方のスレッドの結果を提供できますか? はい- 一部の現在の Intel CPU は、ストア バッファーからの負荷の一部と、L1 からの残りの負荷を満たしますが、どちらのストアもまだグローバルに表示されていないため (まだストア バッファーに残っているため)、var.iv[0] == 1 && var.iv[1] == 0スレッドを実行できます。 1 およびvar.iv[0] == 0 && var.iv[1] == 1スレッド 2 で。

ユーザー Alex は、実際にこのためのテスト コードを作成し、この非常に関連性の高い回答で実演しました。いいえ、ここには魔法のトリックはありません。すべての CPU でこのように独自のロックフリー同期を構築することはできません。

ところで、これ一部の CPU で動作する可能性があります。部分的なストア フォワーディングが存在する場合、一部のモデルは簡単に実行して、ストアが L1 にコミットするまで待機し、L1 から値全体を読み取る場合があります。この場合、あなたのトリックはうまくいきます...しかし、それはあなたに多くをもたらさないでしょう. とにかく、メモリフェンスの主なコストであるストアバッファ全体が排出されるのを待つ必要があります! そのため、最大でもメモリ フェンス サイズのストールで、メモリ フェンス効果が得られます。


1以前のシングル スレッド「では、この場合の 'y' は 0 にできますか?」に対する答え。ケースは明らかに「いいえ」です - CPU は順序どおりに実行されているという錯覚を維持します。そのため、何かを書き込んですぐに読み返すと、書き込みがどのように行われたかに関係なく、常に書き込みが表示されます (他のスレッドが同じ場所に書き込みを行っていない場合)。書き込みと読み取りの重複。

于 2018-06-01T01:46:19.730 に答える
0

CPUは、メモリの場所をエイリアス化したことを認識または認識しません。そのため、最初の質問に対する答えは「いいえ」です。

2番目の例の書き込みは同期されていないため、はい、スレッドがデータの独自のコピーを持つ可能性があります。

あなたが尋ねなかった質問(「カスタム同期プリミティブを実装して使用する必要がありますか?」)に対する答えは「いいえ」です。

于 2012-09-26T17:44:41.673 に答える