アトミック操作(コンペアアンドスワップまたはアトミック加算/デクリメントのいずれか)のコストはいくらですか?どのくらいのサイクルを消費しますか?SMPまたはNUMAで他のプロセッサを一時停止しますか、それともメモリアクセスをブロックしますか?アウトオブオーダーCPUのリオーダーバッファをフラッシュしますか?
キャッシュにはどのような影響がありますか?
x86、x86_64、PowerPC、SPARC、Itaniumなどの最新の人気のあるCPUに興味があります。
アトミック操作(コンペアアンドスワップまたはアトミック加算/デクリメントのいずれか)のコストはいくらですか?どのくらいのサイクルを消費しますか?SMPまたはNUMAで他のプロセッサを一時停止しますか、それともメモリアクセスをブロックしますか?アウトオブオーダーCPUのリオーダーバッファをフラッシュしますか?
キャッシュにはどのような影響がありますか?
x86、x86_64、PowerPC、SPARC、Itaniumなどの最新の人気のあるCPUに興味があります。
回答:
過去数日間の実際のデータを探しましたが、何も見つかりませんでした。ただし、アトミック操作のコストとキャッシュミスのコストを比較する調査を行いました。
lock cmpxchg
PentiumPro(ドキュメントで説明されている)の前のx86 LOCKプレフィックス(アトミックCASを含む)のコストは、メモリアクセス(キャッシュミスなど)、+他のプロセッサによるメモリ操作の停止、+他のプロセッサとの競合ですバスをロックしようとしています。ただし、PentiumPro以降、通常のライトバックキャッシュ可能メモリ(ハードウェアと直接通信しない限り、アプリが処理するすべてのメモリ)の場合、すべてのメモリ操作をブロックする代わりに、関連するキャッシュラインのみがブロックされます(@osgxの回答のリンクに基づく) 。
つまり、コアは、実際のlock
ed操作のストア部分が終了するまで、回線に対するMESI共有およびRFO要求への応答を遅らせます。これは「キャッシュロック」と呼ばれ、その1つのキャッシュラインにのみ影響します。他のコアは、他のラインを同時にロード/保存したり、CASしたりすることもできます。
実際、このページで説明されているように、CASのケースはより複雑になる可能性があり、タイミングはありませんが、信頼できるエンジニアによる洞察に満ちた説明があります。(少なくとも、実際のCASの前に純粋なロードを実行する通常のユースケースでは。)
詳細に入る前に、ロックされた操作には1つのキャッシュミス+同じキャッシュライン上の他のプロセッサとの競合の可能性がありますが、CAS +先行するロード(ミューテックスを除いてほとんど常に必要です。 CAS 0および1)は、2つのキャッシュミスが発生する可能性があります。
彼は、単一の場所でのロード+ CASは、Load-Linked / Store-Conditionalのように実際には2つのキャッシュミスが発生する可能性があると説明しています(後者については、そこを参照してください)。彼の説明は、MESIキャッシュコヒーレンスプロトコルの知識に依存しています。キャッシュラインには4つの状態を使用します:M(odified)、E(xclusive)、S(hared)、I(nvalid)(したがって、MESIと呼ばれます)。必要に応じて以下で説明します。説明されているシナリオは次のとおりです。
いずれの場合も、キャッシュライン要求は、すでにデータを変更している他のプロセッサによって停止する可能性があります。
次の設定でプロファイリングを行いました。テストマシン(AMD Athlon64 x2 3800+)を起動し、ロングモード(割り込みを無効)に切り替え、対象の命令をループで実行し、100回の反復を展開し、1,000回のループサイクルを実行しました。ループ本体は16バイトに揃えられました。時間は、ループの前後にrdtsc命令を使用して測定されました。さらに、命令のないダミーループが実行され(ループの反復ごとに2サイクル、残りの場合は14サイクルが測定されました)、結果は命令プロファイリング時間の結果から差し引かれました。
次の指示が測定されました。
lock cmpxchg [rsp - 8], rdx
"(比較の一致と不一致の両方)、lock xadd [rsp - 8], rdx
"、lock bts qword ptr [rsp - 8], 1
」すべての場合において、測定された時間は約310サイクルであり、誤差は約+/- 8サイクルでした。
これは、同じ(キャッシュされた)メモリで繰り返し実行される値です。キャッシュミスが追加されると、時間が大幅に長くなります。また、これは2つのコアのうち1つだけがアクティブな状態で行われたため、キャッシュは排他的に所有され、キャッシュの同期は必要ありませんでした。
キャッシュミス時のロックされた命令のコストを評価するために、ロックされたwbinvld
命令の前に命令を追加し、wbinvld
プラスをadd [rsp - 8], rax
比較ループに入れました。どちらの場合も、コストは命令ペアあたり約80,000サイクルでした。ロックBTの場合、時間差は1命令あたり約180サイクルでした。
これは相互スループットであることに注意してください。ただし、ロックされた操作はシリアル化操作であるため、レイテンシーに違いはない可能性があります。
結論:ロックされた操作は重いですが、キャッシュミスははるかに重い可能性があります。また、ロックされた操作によってキャッシュミスが発生することはありません。キャッシュラインが排他的に所有されていない場合にのみ、キャッシュ同期トラフィックが発生する可能性があります。
マシンを起動するために、ReactOSプロジェクトのx64バージョンのFreeLdrを使用しました。asmのソースコードは次のとおりです。
#define LOOP_COUNT 1000
#define UNROLLED_COUNT 100
PUBLIC ProfileDummy
ProfileDummy:
cli
// Get current TSC value into r8
rdtsc
mov r8, rdx
shl r8, 32
or r8, rax
mov rcx, LOOP_COUNT
jmp looper1
.align 16
looper1:
REPEAT UNROLLED_COUNT
// nothing, or add something to compare against
ENDR
dec rcx
jnz looper1
// Put new TSC minus old TSC into rax
rdtsc
shl rdx, 32
or rax, rdx
sub rax, r8
ret
PUBLIC ProfileFunction
ProfileFunction:
cli
rdtsc
mov r8, rdx
shl r8, 32
or r8, rax
mov rcx, LOOP_COUNT
jmp looper2
.align 16
looper2:
REPEAT UNROLLED_COUNT
// Put here the code you want to profile
// make sure it doesn't mess up non-volatiles or r8
lock bts qword ptr [rsp - 8], 1
ENDR
dec rcx
jnz looper2
rdtsc
shl rdx, 32
or rax, rdx
sub rax, r8
ret
バスベースのSMPでは、アトミックプレフィックスLOCK
はバスワイヤ信号をアサート(オン)しLOCK#
ます。バス上の他のCPU /デバイスがそれを使用することを禁止します。
Ppro&P2ブックhttp://books.google.com/books?id=3gDmyIYvFH4C&pg=PA245&dq=lock+instruction+pentium&lr=&ei=_E61S5ehLI78zQSzrqwI&cd=1#v=onepage&q=lock%20instruction%20pentium&f=falseページ244-246
ロックされた命令はシリアル化、同期操作です.... / about Out-of-order /ロックされたRMW / read-modify-write =アトミック自体/命令は、プロセッサがロックされた命令の前にすべての命令を実行することを保証します。/約まだフラッシュされていない書き込み/次の命令を実行する前に、プロセッサ内で投稿されたすべての書き込みを外部メモリに強制的にフラッシュします。
/ about SMP /セマフォはS状態のキャッシュにあります...日付の0バイトに対して読み取りおよび無効化トランザクションを発行します(これは隣接するCPUのキャッシュラインの共有コピーの強制終了/です/)
LOCK
データがキャッシュラインにずれている場合を除き、バスは毎回ロック作る、またはキャッシュの競合がありません。最新の番号については、rigtorp.se / split - locksを確認してください。