アトミック操作 (コンペア アンド スワップまたはアトミック アド/デクリメントのいずれか) のコストはいくらですか? どのくらいのサイクルを消費しますか? SMP または NUMA 上の他のプロセッサを一時停止しますか、それともメモリ アクセスをブロックしますか? 順不同の CPU でリオーダー バッファをフラッシュしますか?
キャッシュにはどのような影響がありますか?
x86、x86_64、PowerPC、SPARC、Itanium などの最新の人気のある CPU に興味があります。
アトミック操作 (コンペア アンド スワップまたはアトミック アド/デクリメントのいずれか) のコストはいくらですか? どのくらいのサイクルを消費しますか? SMP または NUMA 上の他のプロセッサを一時停止しますか、それともメモリ アクセスをブロックしますか? 順不同の CPU でリオーダー バッファをフラッシュしますか?
キャッシュにはどのような影響がありますか?
x86、x86_64、PowerPC、SPARC、Itanium などの最新の人気のある CPU に興味があります。
過去数日間の実際のデータを探しましたが、何も見つかりませんでした。ただし、アトミック操作のコストとキャッシュミスのコストを比較する調査を行いました。
PentiumPro(ドキュメントで説明されている)の前のx86 LOCKプレフィックス(lock cmpxchg
アトミックCASを含む)のコストは、メモリアクセス(キャッシュミスなど)、+他のプロセッサによるメモリ操作の停止、+他のプロセッサとの競合ですバスをロックしようとしています。ただし、PentiumPro以降、通常のライトバックキャッシュ可能メモリ(ハードウェアと直接通信しない限り、アプリが処理するすべてのメモリ)では、すべてのメモリ操作をブロックする代わりに、関連するキャッシュラインのみがブロックされます(@osgxの回答のリンクに基づく) 。
lock
つまり、コアは、実際のed操作のストア部分が完了するまで、回線に対するMESI共有およびRFO要求への応答を遅らせます。これは「キャッシュロック」と呼ばれ、その1つのキャッシュラインにのみ影響します。他のコアは、同時に他のラインをロード/保存したり、CASしたりすることもできます。
実際、このページで説明されているように、CASのケースはより複雑になる可能性があり、タイミングはありませんが、信頼できるエンジニアによる洞察に満ちた説明があります。(少なくとも、実際のCASの前に純粋なロードを実行する通常のユースケースでは。)
詳細に入る前に、LOCKed操作には1つのキャッシュミス+同じキャッシュライン上の他のプロセッサとの競合の可能性がありますが、CAS +先行するロード(ミューテックスを除いてほとんどの場合必要です。 CAS 0および1)は、2つのキャッシュミスが発生する可能性があります。
彼は、単一の場所でのロード+ CASは、Load-Linked / Store-Conditional(後者についてはこちらを参照)のように、実際には2つのキャッシュミスが発生する可能性があると説明しています。彼の説明は、 MESIキャッシュコヒーレンスプロトコルの知識に依存しています。キャッシュラインには、M(odified)、E(xclusive)、S(hared)、I(nvalid)(したがって、MESIと呼ばれます)の4つの状態を使用します。これについては、必要に応じて以下で説明します。説明されているシナリオは次のとおりです。
いずれの場合も、キャッシュライン要求は、すでにデータを変更している他のプロセッサによって停止する可能性があります。
次のセットアップでプロファイリングを行いました。テスト マシン (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
プラス anadd [rsp - 8], rax
を比較ループに入れました。どちらの場合も、コストは命令ペアあたり約 80,000 サイクルでした。ロック bts の場合、時間差は命令ごとに約 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 book 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=偽ページ 244-246
ロックされた命令は、操作をシリアル化し、同期しています..../out-of-order/について/ロックされたRMW/read-modify-write =アトミック自体/命令は、プロセッサがロックされた命令を実行する前に、ロックされた命令の前にすべての命令を実行することを保証します。/まだフラッシュされていない書き込みについて/ 次の命令を実行する前に、プロセッサ内のポストされたすべての書き込みを強制的に外部メモリにフラッシュします。
/SMP について/ セマフォは S 状態のキャッシュにあります... データの 0 バイトに対して読み取りおよび無効化トランザクションを発行します (これはキルです/隣接する CPU のキャッシュ ラインの共有コピーの/)