2

インテル アーキテクチャ ソフトウェア開発者マニュアル、 2012年 8 月、vol. 3A、セクション。8.2.2:

2 つのストアは、ストアを実行するプロセッサ以外のプロセッサによって一貫した順序で表示されます。

しかし、これはそうでしょうか?

私が尋ねる理由は次のとおりです。HyperThreading を備えたデュアルコア Intel i7 プロセッサを検討してください。マニュアルのvol 。図 1、図 2-8 では、i7 の論理プロセッサ 0 と 1 は L1/L2 キャッシュを共有していますが、その論理プロセッサ 2 と 3 は別の L1/L2 キャッシュを共有しています。一方、すべての論理プロセッサは単一の L3 キャッシュを共有しています。論理プロセッサ 0 と 2 (L1/L2 キャッシュを共有していない) がほぼ同時に同じメモリ位置に書き込み、書き込みが現時点では L2 よりも深くないと仮定します。論理プロセッサ 1 と 3 (「ストアを実行するプロセッサ以外のプロセッサ」) は、「矛盾した順序で 2 つのストア」​​を認識できませんでしたか?

一貫性を保つために、論理プロセッサ 0 と 2 は SFENCE 命令を発行し、論理プロセッサ 1 と 3 は LFENCE 命令を発行してはいけませんか? それにもかかわらず、マニュアルはそうではないと考えているようであり、この問題に関するその意見は単なる誤植のようには見えません. わざとらしい。よくわかりません。

アップデート

@Benoit の回答に照らして、次の質問: したがって、L1 と L2 の唯一の目的は、負荷を高速化することです。ストアを高速化するのは L3 です。そうですか?

4

3 に答える 3

3

Intel CPU (すべての通常の SMP システムと同様) は、 MESI (の変形) を使用して、キャッシュされたロード/ストアのキャッシュ コヒーレンシを確保します。つまり、すべてのコアがキャッシュを通じてメモリの同じビューを認識します。

コアは、Read For Ownership (RFO) を実行した後にのみキャッシュ ラインに書き込むことができ、ラインを排他的状態にします (他のキャッシュには、負荷を満たすことができるラインの有効なコピーはありません)。関連: アトミック RMW 操作は、他のコアがターゲット キャッシュ ラインに対して何もできないようにするため、操作中は Modified 状態でロックします

この種の並べ替えをテストするには、両方のストアを (反対の順序で) 読み取る 2 つのスレッドが必要です。 提案されたシナリオでは、別のコア (reader1) が writer1 によって格納された同じ行の新しい値を読み取った後に、 1 つのコア (reader2) がメモリ (または L3、または独自のプライベート L2/L1) から古い値を読み取ります。これは不可能です。reader1 が writer1 のストアを参照するには、writer1 はキャッシュ ラインの他のすべてのコピーを無効にする RFO を既に完了している必要があります。また、(事実上) ライトバック キャッシュをスヌーピングせずに DRAM から直接読み取ることは許可されていません。(ウィキペディアの MESI 記事には図があります。)

ストアが (コア内のストア バッファから) L1d キャッシュにコミットされると、他のすべてのコアから同時にグローバルに可視になります。 それ以前は、ローカル コアだけがそれを「見る」ことができました (store->store バッファからのロード転送を介して)。

データが 1 つのコアから別のコアに伝搬される唯一の方法がグローバル キャッシュ コヒーレンシ ドメインを介するシステムでは、MESI キャッシュ コヒーレンシだけで、すべてのスレッドが同意できる単一のグローバル ストア順序が存在することが保証されます。x86 の強力なメモリ順序規則により、このグローバル ストア順序はプログラム順序のインターリーブになります。これを Total Store Order メモリ モデルと呼びます。

x86 の強力なメモリ モデルでは、LoadLoad の並べ替えが許可されていないため、読み込みは、リーダー スレッドでのバリア命令なしで、プログラムの順序でキャッシュからデータを取得します。1

ロードは、コヒーレント キャッシュからデータを取得する前に、ローカル ストア バッファーを実際にスヌープします。 これが、引用した一貫した順序ルールが、ロードを実行している同じコアによっていずれかのストアが実行された場合を除外する理由です。ロード データが実際にどこから来るかについての詳細は、 Globally Invisible load instructionを 参照してください。しかし、ロード アドレスが最近のストアと重複していない場合は、上で述べたことが当てはまります。ロード順序は、共有されたグローバルにコヒーレントなキャッシュ ドメインからのサンプリングの順序です。


一貫した順序規則は、かなり弱い要件です。x86 以外の多くの ISA では紙面で保証されていませんが、実際の (x86 以外の) CPU 設計には、すべてのコアがグローバルに認識できるようになる前に、あるコアが別のコアからのストア データを参照できるメカニズムがほとんどありません。IBM POWER with SMT はそのような例の 1 つです。異なるスレッドの異なる場所への 2 つのアトミックな書き込みは、他のスレッドからは常に同じ順序で表示されますか? は、1 つの物理コア内の論理コア間の転送がどのように発生するかを説明しています。(これはあなたが提案したものと似ていますが、L2ではなくストアバッファ内にあります)。

ハイパースレッディング (または Ryzen での AMD の SMT) を備えた x86 マイクロアーキテクチャは、1 つの物理コア上の論理コア間でストア バッファーを静的に分割することにより、その要件に従います。 HT を使用して 1 つの Core で実行されているスレッド間のデータ交換には何が使用されますか? そのため、1 つの物理コア内であっても、他の論理コアが新しいデータをロードできるようになる前に、ストアが L1d にコミットする (そしてグローバルに可視になる) 必要があります。

1 つの論理コアのリタイアしたがコミットされていないストアから、同じ物理コアの他の論理コアへの転送を持たない方がおそらく簡単です。

(x86 の TSO メモリ モデルのその他の要件 (プログラムの順序で表示されるロードとストアなど) はより困難です。最新の x86 CPU は順不同で実行されますが、メモリ オーダー バッファを使用して錯覚を維持し、プログラムの順序でストアを L1d にコミットさせます。ロードは、「想定」されるよりも前に投機的に値を取得し、後でチェックすることができます. これが、Intel CPU が「メモリ順序の誤った投機」パイプライン核を持っている理由です :ハイパー兄弟と非ハイパー兄弟の間の記憶場所? .)

@BeeOnRope が指摘するように、HT と LoadLoad の並べ替えがないという錯覚を維持することの間に相互作用があります。通常、CPU は、ロードが実際にキャッシュ ラインを読み取った後、アーキテクチャ上で読み取りが許可される前に、別のコアがキャッシュ ラインに触れたことを検出できます。ロード ポートは、そのキャッシュ ラインに対する無効化を追跡できます。しかし、HT では、ロード ポートは、他のハイパースレッドが L1d キャッシュにコミットするストアをスヌープする必要もあります。これは、ラインが無効にならないためです。(他のメカニズムも可能ですが、「通常の」負荷で高いパフォーマンスが必要な場合、CPU 設計者が解決しなければならない問題です。)


脚注 1 : 順序付けが弱い ISA では、ロード順序付けバリアを使用して、各リーダーの 2 つのロードがグローバルに一貫したキャッシュ ドメインからデータを取得する順序を制御します。

ライター スレッドはそれぞれ 1 つのストアしか実行しないため、フェンスは無意味です。すべてのコアが 1 つの一貫したキャッシュ ドメインを共有するため、フェンスはコア内のローカルな並べ替えを制御するだけで済みます。各コアのストア バッファは、(ISA の順序付け規則を尊重しながら) できるだけ早くストアをグローバルに表示できるように既に試みているため、バリアは、後の操作を実行する前に CPU を待機させるだけです。

x86lfenceには基本的にメモリ順序付けのユース ケースsfenceがなく、NT ストアでのみ役立ちます。あるスレッドが何かを書き込んでから別の場所を読み取る場合にのみmfence、「通常の」ものに役立ちます。 http://preshing.com/20120515/memory-reordering-caught-in-the-act/ . そのため、バリアを越えて StoreLoad の並べ替えとストア転送がブロックされます。


@Benoit の回答に照らして、次の質問: したがって、L1 と L2 の唯一の目的は、負荷を高速化することです。ストアを高速化するのは L3 です。そうですか?

いいえ、L1d と L2 はライトバック キャッシュです。Intel Core i7 プロセッサで使用されているキャッシュ マッピング手法はどれですか? . 同一ラインへの重複ストアはL1dで吸収できます。

しかし、Intel は包括的 L3 キャッシュを使用しています。L3 は実際にはタグを含みます。これは、L3 タグがスヌープ フィルターとして機能するために必要なすべてです (すべてのコアに RFO 要求をブロードキャストする代わりに)。ダーティ ラインの実際のデータは、コアごとの内部キャッシュにプライベートですが、L3 はどのコアがラインの現在のデータを持っているかを知っています (したがって、別のコアが別のコアが Modified に持っているラインを読み取りたい場合に、どこにリクエストを送信するか)州)。クリーン キャッシュ ライン (共有状態) は L3 のデータを含みますが、キャッシュ ラインへの書き込みは L3 へのライトスルーではありません。

于 2018-06-26T00:16:53.747 に答える
1

Intel のドキュメントが言っていることは、x86 チップの仕組みにより、他のプロセッサが常に一貫した順序で書き込みを確認できるようになるということだと思います。

そのため、他のプロセッサは、そのメモリの場所を読み取るときに、次のいずれかの結果しか表示しません。

  • いずれかの書き込み前の値 (つまり、読み取りが両方の書き込みに先行する)

  • プロセッサ 0 の書き込み後の値 (つまり、プロセッサ 2 が最初に書き込み、次にプロセッサ 0 が上書きしたかのように)

  • プロセッサ 2 の書き込み後の値 (つまり、プロセッサ 0 が最初に書き込み、次にプロセッサ 2 が上書きしたかのように)

プロセッサ 1 がプロセッサ 0 の書き込み後に値を確認することはできませんが、同時にプロセッサ 3 はプロセッサ 2 の書き込み後に値を確認できます (またはその逆)。

プロセッサ内での並べ替えが許可されているため (セクション 8.2.3.5 を参照)、プロセッサ 0 と 2 では物事が異なって見える場合があることに注意してください。

于 2013-01-09T05:00:45.510 に答える
0

うーん、これは難しい質問です!でもやってみます...

書き込みは L2 より深くはなりません

Intel は包括的キャッシュを使用するため、基本的にこれは不可能です。L1 に書き込まれたデータは、CR0/MTRR を使用してキャッシュを無効にしてキャッシュを防止しない限り、L2 と L3 でも行われます。

そうは言っても、調停メカニズムがあると思います。プロセッサはデータを書き込むリクエストを発行し、アービターは各リクエストキューからの保留中のリクエストの中からどのリクエストが許可されるかを選択します。選択されたリクエストはスヌーパーにブロードキャストされ、次にキャッシュに送信されます。競合を防ぎ、リクエストを実行するプロセッサ以外のプロセッサから見た一貫した順序を強制すると思います。

于 2013-01-09T14:45:53.893 に答える