web-dev-qa-db-ja.com

原子操作コスト

アトミック操作のコストはいくらですか(比較とスワップまたはアトミックな追加/減少のいずれか)?どのくらいのサイクルを消費しますか? SMPまたはNUMA上の他のプロセッサを一時停止しますか、それともメモリアクセスをブロックしますか?異常なCPUのリオーダーバッファをフラッシュしますか?

キャッシュにどのような影響がありますか?

X86、x86_64、PowerPC、SPARC、Itaniumなどの最新の人気のあるCPUに興味があります。

77
osgx

私は過去数日間の実際のデータを探しましたが、何も見つかりませんでした。ただし、アトミック操作のコストとキャッシュミスのコストを比較する調査をいくつか行いました。

PentiumPro(ドキュメントで説明されている)の前のx86 LOCKプレフィックス、またはCASのコストは、メモリアクセス(キャッシュミスなど)、+他のプロセッサによるメモリ操作の停止、+他のプロセッサとのロックの競合バス。ただし、PentiumProの場合、ライトバック(キャッシュ可能な)メモリ(ハードウェアと直接話さない限り、アプリが処理するすべてのメモリ)では、すべてのメモリ操作をブロックするのではなく、関連するキャッシュラインのみがブロックされます(上記のリンクに基づいて)。

実際、CASのケースは このページ で説明されているように、タイミングはありませんが、信頼できるエンジニアによる洞察に満ちた説明が含まれているため、より複雑になる可能性があります。

詳細を説明する前に、ロックされた操作には1つのキャッシュミス+同じキャッシュライン上の他のプロセッサとの競合の可能性がありますが、CAS +前の負荷(mutexを除き、ほとんど常に必要です) CAS 0および1)では、2つのキャッシュミスが発生する可能性があります。

彼は、単一の場所での負荷+ CASには、実際にはLoad-Linked/Store-Conditionalなどの2つのキャッシュミスが発生する可能性があると説明しています(後者については、こちらを参照)。彼の説明は MESIキャッシュコヒーレンスプロトコル の知識に依存しています。キャッシュラインに4つの状態を使用します:M(odified)、E(xclusive)、S(hared)、I(nvalid)(したがって、MESIと呼ばれます)、必要に応じて以下で説明します。説明されているシナリオは次のとおりです。

  • lOADによりキャッシュミスが発生します-関連するキャッシュラインはShared状態のメモリからロードされます(つまり、他のプロセッサはそのキャッシュラインをメモリに保持できます。この状態では変更は許可されません)。場所がメモリ内にある場合、このキャッシュミスはスキップされます。 可能コスト:1キャッシュミス(キャッシュラインが共有、排他、または変更状態の場合、つまり、データがこのCPUのL1キャッシュにある場合はスキップされます)。
  • プログラムは保存する新しい値を計算し、
  • そして、それはアトミックCAS命令を実行します。
    • 同時変更を回避する必要があるため、キャッシュラインをExclusive状態に移行するには、他のCPUのキャッシュからキャッシュラインのコピーを削除する必要があります。 可能性のあるコスト:1キャッシュミス。これが既に排他的に所有されている場合、つまりExclusive状態またはModified状態にある場合、これは必要ありません。どちらの状態でも、他のCPUはキャッシュラインを保持していませんが、排他的状態では(まだ)変更されていません。
    • この通信の後、変数はCPUのローカルキャッシュで変更され、その時点で他のすべてのCPUにグローバルに表示されます(キャッシュはキャッシュと一貫性があるため)。最終的には、通常のアルゴリズムに従ってメインメモリに書き込まれます。
    • その変数を読み取りまたは変更しようとする他のプロセッサーは、まず共有モードまたは排他モードでそのキャッシュラインを取得する必要があります。そうすると、このプロセッサーに接続して、キャッシュラインの更新バージョンを受け取ります。代わりに、ロックされた操作では、キャッシュミスが発生するだけです(キャッシュラインは排他状態で直接要求されるため)。

すべての場合において、すでにデータを変更している他のプロセッサによってキャッシュライン要求が停止する可能性があります。

52
Blaisorblade

次のセットアップでプロファイリングを行いました:テストマシン(AMD Athlon64 x2 3800+)が起動され、ロングモードに切り替えられ(割り込みが無効)、目的の命令がループで実行されました。ループ本体は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命令を追加し、wbinvldadd [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
34
Timo

バスベースの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/locked RMW/read-modify-write = atomic自体/命令プロセッサは、実行前にロックされた命令の前にすべての命令を実行します。 /約まだフラッシュされていない書き込み/次の命令を実行する前に、プロセッサ内のすべてのポストされた書き込みを外部メモリに強制的にフラッシュします。

/ about SMP /セマフォはS状態でキャッシュにあります... 0バイトの日付で読み取りおよび無効化トランザクションを発行します(これは、隣接するCPUのキャッシュラインの共有コピーの削除/です)

4
osgx