「Intel 最適化ガイド Guide For Intel Architecture」を読みました。
ただし、いつ使用するかについてはまだわかりません
_mm_sfence()
_mm_lfence()
_mm_mfence()
マルチスレッド コードを記述するときにこれらをいつ使用する必要があるか、誰か説明できますか?
「Intel 最適化ガイド Guide For Intel Architecture」を読みました。
ただし、いつ使用するかについてはまだわかりません
_mm_sfence()
_mm_lfence()
_mm_mfence()
マルチスレッド コードを記述するときにこれらをいつ使用する必要があるか、誰か説明できますか?
これが私の理解です。うまくいけば正確で、意味をなすのに十分単純です。
(Itanium) IA64 アーキテクチャでは、メモリの読み取りと書き込みを任意の順序で実行できるため、フェンスを使用して書き込みが適切な順序で完了するように強制しない限り、別のプロセッサの観点から見たメモリ変更の順序は予測できません。
ここから先はx86の話ですが、x86は強く注文されています。
x86 では、Intel は、別のプロセッサで行われたストアが常にこのプロセッサですぐに表示されることを保証しません。このプロセッサが投機的にロード (読み取り) を実行し、他のプロセッサのストア (書き込み) を見逃した可能性があります。書き込みが他のプロセッサに見えるようになる順序がプログラムの順序であることを保証するだけです。何をしても、他のプロセッサが更新をすぐに認識できるとは限りません。
ロックされた読み取り/変更/書き込み命令は、完全にシーケンシャルに一貫性があります。このため、一般に、他のプロセッサのメモリ操作の欠落を既に処理しています。これは、ロックされているxchg
かcmpxchg
、すべてが同期されているためです。所有権のために関連するキャッシュ ラインをすぐに取得し、アトミックに更新します。ロックされた操作で別の CPU が競合している場合、競合に勝ち、他の CPU がキャッシュを失い、ロックされた操作の後にそれを取り戻すか、競合に勝ち、キャッシュを逃して更新を取得します。それらからの価値。
lfence
lfence
前のすべての命令が完了するまで、命令の発行を停止します。mfence
具体的には、先行するすべてのメモリ読み取りがデスティネーション レジスタに完全に取り込まれるのを待機し、先行するすべての書き込みがグローバルに可視になるのを待機しますが、その後のすべての命令のように停止しませんlfence
。sfence
は、ストアのみに対して同じことを行い、書き込みコンバイナをフラッシュし、sfence
に続くすべてのストアが実行を開始できるようにする前に、 に先行するすべてのストアがグローバルに表示されるようにsfence
します。
x86 では、あらゆる種類のフェンスが必要になることはめったにありません。カーネル モード (ドライバー) 開発者でない場合は、書き込み結合メモリまたは非一時的な命令を使用する場合を除いて、フェンスはほとんど必要ありません。通常、x86 は、すべてのストアがプログラムの順序で表示されることを保証しますが、WC (書き込み結合) メモリや、明示的に弱く順序付けされたストアを実行する「一時的ではない」命令 ( movnti
.
したがって、要約すると、特別な弱い順序付けのストアを使用したり、WC メモリ タイプにアクセスしたりしない限り、ストアは常にプログラムの順序で表示されます。xchg
、 またはxadd
、 またはなどのロックされた命令を使用するアルゴリズムはcmpxchg
、ロックされた命令がシーケンシャルに一貫しているため、フェンスなしで機能します。
警告: 私はこれの専門家ではありません。私はまだこれを自分で学ぼうとしています。しかし、過去 2 日間に誰も回答していないため、メモリ フェンス命令の専門家はあまり多くないようです。だからここに私の理解があります...
Intel は弱順序メモリ システムです。つまり、プログラムが実行される可能性があります
array[idx+1] = something
idx++
ただし、idxへの変更は、 arrayへの変更の前にグローバルに表示される場合があります (たとえば、他のプロセッサで実行されているスレッド/プロセスに対して) 。2 つのステートメントの間にフェンスを配置すると、書き込みが FSB に送信される順序が保証されます。
その間、別のプロセッサが実行されます
newestthing = array[idx]
配列のメモリをキャッシュし、古いコピーを持っている可能性がありますが、キャッシュ ミスのために更新されたidxを取得します。解決策は、事前にlfenceを使用して、負荷が確実に同期されるようにすることです。