多くの場合、インターネットに私はすなわち、それが原因でLFENCE
= MFENCE
+ SFENCE
= MFENCE
+ SFENCE
= LFENCE
、その代わりに、私たちは絶対にSFENCE
使用する無痛できNOP
、何もしない、プロセッサは、x86でそのSFENCE
は意味がありません見つけます。
しかし、LFENCE
が意味をなさない場合は、x86/x86_64で順次整合性を確保するために4つの方法があるのはなぜですか。
LOAD
(フェンスなし)およびSTORE
+ MFENCE
LOAD
(フェンスなし)および_LOCK XCHG
_MFENCE
+ LOAD
およびSTORE
(フェンスなし)LOCK XADD
_(0)およびSTORE
(フェンスなし)ここから取得: http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html
下部の34ページの「ハーブサッター」のパフォーマンス: https://skydrive.live.com/view.aspx?resid=4E86B0CF20EF15AD!24884&app=WordPdf&wdo=2&authkey=!AMtj_EflYn2507c
LFENCE
が何もしなかった場合、アプローチ(3)の意味はSFENCE + LOAD and STORE (without fence)
になりますが、SFENCE
の前にLOAD
を実行しても意味がありません。つまり、LFENCE
が何もしない場合、アプローチ(3)は意味がありません。
プロセッサx86/x86_64でLFENCE
は意味のある命令ですか?
回答:
1。LFENCE
は、以下の承認された回答に記載されている場合に必要です。
2。アプローチ(3)は、個別にではなく、前のコマンドと組み合わせて表示する必要があります。たとえば、アプローチ(3):
_MFENCE
MOV reg, [addr1] // LOAD-1
MOV [addr2], reg //STORE-1
MFENCE
MOV reg, [addr1] // LOAD-2
MOV [addr2], reg //STORE-2
_
アプローチ(3)のコードは次のように書き換えることができます。
_SFENCE
MOV reg, [addr1] // LOAD-1
MOV [addr2], reg //STORE-1
SFENCE
MOV reg, [addr1] // LOAD-2
MOV [addr2], reg //STORE-2
_
そして、ここでSFENCE
は、STORE-1とLOAD-2の順序変更を防ぐのに意味があります。このため、STORE-1コマンドの後、SFENCE
はStore-Bufferをフラッシュします。
結論(TL; DR):LFENCE
だけでは、実際にはメモリの順序付けには役に立たないようですが、SFENCE
をMFENCE
の代わりに使用することはできません。質問の「算術」ロジックは適用されません。
インテルのソフトウェア開発者向けマニュアル、ボリューム 、セクション8.2.2(2014年9月の版325384-052US)からの抜粋です。これは 別の回答 で使用したものと同じです。
- 読み取りは他の読み取りと並べ替えられません。
- 書き込みは、古い読み取りでは並べ替えられません。
- メモリへの書き込みは、次の例外を除いて、他の書き込みと並べ替えられません。
- cLFLUSH命令で実行された書き込み。
- 非時間移動命令(MOVNTI、MOVNTQ、MOVNTDQ、MOVNTPS、およびMOVNTPD)で実行されるストリーミングストア(書き込み)。そして
- 文字列操作(セクション8.2.4.1を参照)。
- 読み取りは、異なる場所への古い書き込みでは並べ替えられますが、同じ場所への古い書き込みでは並べ替えられません。
- 読み取りまたは書き込みは、I/O命令、ロックされた命令、またはシリアル化命令で並べ替えることはできません。
- 読み取りは、以前のLFENCEおよびMFENCE命令を渡すことはできません。
- 以前のLFENCE、SFENCE、およびMFENCE命令を書き込むことはできません。
- LFENCE命令は以前の読み取りを渡すことができません。
- SFENCE命令は以前の書き込みを渡すことができません。
- MFENCE命令は、以前の読み取りまたは書き込みを渡すことができません。
ここからは、次のようになります。
MFENCE
は、非一時的かどうかにかかわらず、すべてのメモリタイプのすべての操作に対する完全なメモリフェンスです。SFENCE
は書き込みの並べ替えを防止するだけであり(他の用語では、StoreStoreバリアです)、非一時的なストアや例外としてリストされている他の命令と一緒にのみ役立ちます。LFENCE
は、後続の読み取りと書き込みを伴う読み取りの並べ替えを防ぎます(つまり、LoadLoadバリアとLoadStoreバリアを組み合わせます)。ただし、最初の2つの箇条書きは、LoadLoadバリアとLoadStoreバリアが常に配置されていることを示しており、例外はありません。したがって、LFENCE
だけではメモリの順序付けには役に立ちません。最後の主張を裏付けるために、Intelのマニュアルの3巻すべてでLFENCE
が言及されているすべての場所を調べましたが、LFENCE
がメモリの一貫性のために必要であると言うことはありませんでした。 MOVNTDQA
-現時点で唯一の非時間的ロード命令-MFENCE
については言及していますが、LFENCE
については言及していません。
更新:以下の当て推量に対する正しい答えについては、 なぜですか(そうでないのですか?)SFENCE + LFENCEはMFENCEと同等ですか? の回答を参照してください
MFENCE
が他の2つのフェンスの「合計」に等しいかどうかは、難しい問題です。一見すると、3つのフェンス命令のうち、MFENCE
のみがStoreLoadバリアを提供します。つまり、以前の書き込みでの読み取りの並べ替えを防止します。しかし、正しい答えは上記のルール以上を知る必要があります。つまり、すべてのフェンス命令が互いに関して順序付けられていることが重要です。これはSFENCE LFENCE
シーケンスは、個々のエフェクトの単なる和集合よりも強力です。このシーケンスは、StoreLoadの並べ替えも防止します(ロードがLFENCE
を渡すことができず、SFENCE
を渡すことができず、ストアを渡すことができないため)。完全なメモリフェンス(ただし、下の注(*)も参照)。ただし、ここでは順序が重要であり、LFENCE SFENCE
シーケンスは同じ相乗効果を持ちません。
ただし、MFENCE ~ SFENCE LFENCE
およびLFENCE ~ NOP
、という意味ではありませんMFENCE ~ SFENCE
。ここでは、算術規則がここでは適用されないことを強調するために、等価(〜)と等価ではない(=)を意図的に使用しています。 SFENCE
とそれに続くLFENCE
の相互影響により違いが生じます。ロードが相互に並べ替えられない場合でも、LFENCE
を使用したロードの並べ替えを防ぐにはSFENCE
が必要です。
(*)MFENCE
は他の2つのフェンスの組み合わせよりも強力であると言っても正しいかもしれません。特に、Intelのマニュアルの第2巻にあるCLFLUSH
命令への注記では、「CLFLUSH
はMFENCE
命令によってのみ順序付けられます。順序付けは保証されません。その他のフェンシングまたはシリアル化命令、または別のCLFLUSH
命令による。」
(更新、clflush
は強い順序付けとして定義されるようになりました(通常のストアのように、後でブロックする場合のみmfence
が必要ですloads )、ただしclflushopt
は弱い順序付けですが、sfence
でフェンスできます。)
次のシナリオを検討してください-これは、理論的なロードの実行が理論的にシーケンシャルな一貫性を損なう可能性がある重大なケースです
最初は[x] = [y] = 0
CPU0: CPU1:
store [x]<--1 store [y]<--1
load r1<--[y] load r2<--[x]
X86では、以前のストアで別のアドレスにロードを並べ替えることができるため、どちらのロードも0を返す場合があります。各ストアの後に単独でフェンスを追加しても、同じコンテキスト内での並べ替えが妨げられるだけではありません。ただし、ストアがリタイア後にディスパッチされるため、ストアが実行および監視される前に、両方のフェンスと両方のロードをコミットできます。
一方、mfenceは、ストアを強制的に実行し、その後ロードの実行を許可するため、更新されたデータが表示されます少なくとも1つのコンテキスト。
sfencesと同様に、コメントで指摘されているように、理論的には、その上にロードが並べ替えられないようにするほど強力ではないため、まだ古くなっている可能性がありますデータ。これは、メモリの公式の順序付け規則が適用される限りは当てはまりますが、x86 uarchの現在の実装により、多少強化されると思います(将来的にはそうすることを約束しませんが)。 この説明 によると:
強力なx86順序モデルのため、ロードバッファーはコヒーレンシトラフィックによってスヌーピングされます。リモートストアは、キャッシュラインの他のすべてのコピーを無効にする必要があります。キャッシュラインがロードによって読み取られ、リモートストアによって無効化された場合、無効なデータを読み取る可能性があるため、ロードをキャンセルする必要があります。 x86メモリモデルでは、ストアバッファをスヌーピングする必要はありません。
したがって、マシンでまだコミットされていない負荷は、他のコアからのストアによってスヌープできるはずです。これにより、での負荷の観測時間がcommitポイントであり、executionポイントではありません(実際に順序が狂っており、以前に実行された可能性があります) )。コミットは順番に行われるため、前の指示の後に負荷を監視する必要があります。上記のコメントで述べたように、フェンスは無用に一貫性を維持できるため、フェンスはほとんど役に立ちません。これは主に推測であり、x86でlfencesは無意味であるという一般的な概念を説明しようとします-それがどこで発生したのか完全に定かではありません。
上記はすべて、WB memタイプのコースにのみ適用されます