問題タブ [compare-and-swap]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - Java の比較と交換のセマンティクスとパフォーマンス
Javaでの比較とスワップのセマンティクスは何ですか? つまり、異なるスレッド間のアトミック整数インスタンスの特定のメモリ位置への順序付きアクセスを保証するだけの比較およびスワップ メソッドですかAtomicInteger
、それともメモリ内のすべての位置への順序付きアクセスを保証しますか。つまり、あたかも揮発性であるかのように動作します。 (メモリーフェンス)。
ドキュメントから:
weakCompareAndSet
変数をアトミックに読み取り、条件付きで書き込みますが、先行発生順序付けは作成しません。そのため、 のターゲット以外の変数の前後の読み取りおよび書き込みに関して保証はありませんweakCompareAndSet
。compareAndSet
などの他のすべての読み取りおよび更新操作にgetAndIncrement
は、揮発性変数の読み取りと書き込みの両方のメモリ効果があります。
compareAndSet
揮発性変数であるかのように機能するAPI ドキュメントから明らかです。ただし、weakCompareAndSet
特定のメモリの場所を変更するだけです。したがって、そのメモリ位置が単一のプロセッサのキャッシュ専用である場合、weakCompareAndSet
は通常の よりもはるかに高速であると考えられますcompareAndSet
。
これを尋ねているのは、1 から 8 までthreadnum
のさまざまなスレッドを実行して次のメソッドのベンチマークを行ったからです (コードは静的にコンパイルされた JVM 言語である Scala で記述されていますが、その意味とバイトコード変換の両方がこの場合の Java のそれ - この短いスニペットは明確なはずです):threadnum
totalwork=1e9
4 つのデュアル 2.8 GHz コアと 2.67 GHz 4 コア i7 プロセッサを搭載した AMD 上。JVM は Sun Server Hotspot JVM 1.6 です。結果は、パフォーマンスの違いを示していません。
仕様: AMD 8220 4x デュアルコア @ 2.8 GHz
テスト名: loop_atomic_tlocal_cas
- スレッド番号: 1
実行時間: (最後の 3 つを表示) 7504.562 7502.817 7504.626 (平均 = 7415.637 分 = 7147.628 最大 = 7504.886 )
- スレッド番号: 2
実行時間: (最後の 3 つを表示) 3751.553 3752.589 3751.519 (平均 = 3713.5513 分 = 3574.708 最大 = 3752.949 )
- スレッド番号: 4
実行時間: (最後の 3 つを表示) 1890.055 1889.813 1890.047 (平均 = 2065.7207 分 = 1804.652 最大 = 3755.852 )
- スレッド番号: 8
実行時間: (最後の 3 つを表示) 960.12 989.453 970.842 (平均 = 1058.8776 分 = 940.492 最大 = 1893.127 )
テスト名: loop_atomic_weakcas
- スレッド番号: 1
実行時間: (最後の 3 つを表示) 7325.425 7057.03 7325.407 (平均 = 7231.8682 分 = 7057.03 最大 = 7325.45 )
- スレッド番号: 2
実行時間: (最後の 3 つを表示) 3663.21 3665.838 3533.406 (平均 = 3607.2149 分 = 3529.177 最大 = 3665.838 )
- スレッド番号: 4
実行時間: (最後の 3 つを表示) 3664.163 1831.979 1835.07 (平均 = 2014.2086 分 = 1797.997 最大 = 3664.163 )
- スレッド番号: 8
実行時間: (最後の 3 つを表示) 940.504 928.467 921.376 (平均 = 943.665 分 = 919.985 最大 = 997.681 )
テスト名: loop_atomic_tlocal_weakcas
- スレッド番号: 1
実行時間: (最後の 3 つを表示) 7502.876 7502.857 7502.933 (平均 = 7414.8132 分 = 7145.869 最大 = 7502.933 )
- スレッド番号: 2
実行時間: (最後の 3 つを表示) 3752.623 3751.53 3752.434 (平均 = 3710.1782 分 = 3574.398 最大 = 3752.623 )
- スレッド番号: 4
実行時間: (最後の 3 つを表示) 1876.723 1881.069 1876.538 (平均 = 4110.4221 分 = 1804.62 最大 = 12467.351 )
- スレッド番号: 8
実行時間: (最後の 3 つを表示) 959.329 1010.53 969.767 (平均 = 1072.8444 分 = 959.329 最大 = 1880.049 )
仕様: Intel i7 クアッドコア @ 2.67 GHz
テスト名: loop_atomic_tlocal_cas
- スレッド番号: 1
実行時間: (最後の 3 つを表示) 8138.3175 8130.0044 8130.1535 (平均 = 8119.2888 分 = 8049.6497 最大 = 8150.1950 )
- スレッド番号: 2
実行時間: (最後の 3 つを表示) 4067.7399 4067.5403 4068.3747 (平均 = 4059.6344 分 = 4026.2739 最大 = 4068.5455 )
- スレッド番号: 4
実行時間: (最後の 3 つを表示) 2033.4389 2033.2695 2033.2918 (平均 = 2030.5825 分 = 2017.6880 最大 = 2035.0352 )
テスト名: loop_atomic_weakcas
- スレッド番号: 1
実行時間: (最後の 3 つを表示) 8130.5620 8129.9963 8132.3382 (平均 = 8114.0052 分 = 8042.0742 最大 = 8132.8542 )
- スレッド番号: 2
実行時間: (最後の 3 つを表示) 4066.9559 4067.0414 4067.2080 (平均 = 4086.0608 分 = 4023.6822 最大 = 4335.1791 )
- スレッド番号: 4
実行時間: (最後の 3 つを表示) 2034.6084 2169.8127 2034.5625 (平均 = 2047.7025 分 = 2032.8131 最大 = 2169.8127 )
テスト名: loop_atomic_tlocal_weakcas
- スレッド番号: 1
実行時間: (最後の 3 つを表示) 8132.5267 8132.0299 8132.2415 (平均 = 8114.9328 分 = 8043.3674 最大 = 8134.0418 )
- スレッド番号: 2
実行時間: (最後の 3 つを表示) 4066.5924 4066.5797 4066.6519 (平均 = 4059.1911 分 = 4025.0703 最大 = 4066.8547 )
- スレッド番号: 4
実行時間: (最後の 3 つを表示) 2033.2614 2035.5754 2036.9110 (平均 = 2033.2958 分 = 2023.5082 最大 = 2038.8750 )
上記の例のスレッド ローカルが同じキャッシュ ラインで終了する可能性はありますが、通常の CAS とその脆弱なバージョンとの間に目に見えるパフォーマンスの違いはないように思えます。
これは、実際には、弱い比較とスワップが本格的なメモリ フェンスとして機能する、つまり、揮発性の変数であるかのように機能することを意味する可能性があります。
質問: この観察は正しいですか? また、弱い比較と設定が実際に高速な既知のアーキテクチャまたは Java ディストリビューションはありますか? そうでない場合、そもそも弱い CAS を使用する利点は何ですか?
c++ - C++0x の比較と交換
C++ Atomic Types and Operations に関する C ++0x の提案から:
29.1 順序と一貫性 [atomics.order]
次のパラグラフを含む新しいサブ条項を追加します。
列挙
memory_order
は、[N2334 または採用された後継によって追加された新しいセクション] で定義されているように、詳細な通常の (非アトミック) メモリ同期順序を指定し、操作の順序付けを提供する場合があります。その列挙値とその意味は次のとおりです。
memory_order_relaxed
この操作はメモリを順序付けません。
memory_order_release
影響を受けるメモリ位置で解放操作を実行し、それが適用されるアトミック変数を通じて、通常のメモリ書き込みを他のスレッドから見えるようにします。
memory_order_acquire
影響を受けるメモリ位置で取得操作を実行し、それが適用されるアトミック変数を介して解放された他のスレッドでの通常のメモリ書き込みを、現在のスレッドから見えるようにします。
memory_order_acq_rel
この操作には、取得と解放の両方のセマンティクスがあります。
memory_order_seq_cst
この操作には、取得セマンティクスと解放セマンティクスの両方があり、さらに、操作の順番に一貫性があります。
提案の下:
ここで、CAS のメモリ順序を指定できます。
私の理解では、「<code>memory_order_acq_rel」は操作に必要なメモリ ロケーションのみを同期し、他のメモリ ロケーションは同期されないままになる可能性があります (メモリ フェンスとして動作しません)。
さて、私の質問は、「<code>memory_order_acq_rel」を選択compare_swap
して整数などの整数型に適用する場合、これは通常、マルチコア Intel i7 などの最新のコンシューマ プロセッサのマシン コードにどのように変換されるのでしょうか? 他の一般的に使用されているアーキテクチャ (x64、SPARC、ppc、arm) はどうですか?
具体的には (gcc などの具体的なコンパイラを想定):
- 上記の操作で整数の位置を比較して交換する方法は?
- そのようなコードはどのような命令シーケンスを生成しますか?
- i7での操作はロックフリーですか?
- このような操作は、完全なキャッシュ コヒーレンス プロトコルを実行し、i7 のメモリ フェンスであるかのように、異なるプロセッサ コアのキャッシュを同期しますか? それとも、この操作に必要なメモリ位置を同期するだけですか?
- 前の質問に関連して -
acq_rel
i7 でセマンティクスを使用すると、パフォーマンス上の利点はありますか? 他のアーキテクチャはどうですか?
すべての答えをありがとう。
c - C の機械語コードの比較と交換
組み込みのマシン コード (たとえば、x86 アーキテクチャを想定) を使用して、アトミックな比較と整数値のスワップを行う C の関数をどのように記述しますか? i7 プロセッサ専用に書かれている場合、より具体的に言えますか?
変換はメモリ フェンスとして機能しますか?それとも、比較とスワップに含まれるそのメモリ位置だけで順序付け関係を保証するだけですか? メモリフェンスと比較してどれくらいコストがかかりますか?
ありがとうございました。
c++ - CASテンプレートを作成しようとしています
現時点では、CAS操作とロック/待機なしのアルゴリズムをいじるのに忙しく、自分の正気のために、すべてのキャストを処理するためのテンプレートを実装することにしました。
VC6:
GCC 4.4.1:
volatile
ただし、いくつかの簡単なテストコードを使用すると、これを宛先で機能させることができません。これは、並べ替えを防ぐために必要です。
テストコード:
VC6では、次のエラーが発生します。
そしてGCCはこれを吐き出します:
volatile
宛先がマクロである場合、またはマクロでスタックしている場合に壊れないCAS opsのテンプレートを取得することは可能ですか?
c++ - 「ABA」問題を理解するのに助けが必要
ABA問題についての記事を読んだのですが、理解できないことがあります。私はソースコードを持っていますが、それは機能せず、記事の例に似ていますが、問題を理解していません。これが記事です
http://fara.cs.uni-potsdam.de/~jsg/nucleus/index.php?itemid=6
それは言う:head_の実際の値は同じですが(a)next_ポインタはそうではありません
しかし、どうしてそれができるのでしょうか?2つの構造オブジェクトの場合
「head_」と「current」はメモリ内の同じ領域を指しますが、head _->nextとcurrent->nextはどのように異なるポイントを指すことができますか?
また、次のようにも述べています。最後の操作であるfooによるコンペアアンドスワップは、成功すべきではない場合に成功します。
それでは、それは何をすべきでしょうか?同じアドレスをロードして再試行しますか?違いはなんですか?
現在、私のコードでは、オブジェクトに対してCompareAndSwapを実行するという同様の状況があります。これは、別のスレッドによって、同様のアドレスを持つオブジェクトに変更される可能性があります。
しかし、変更されたオブジェクトが適切に初期化されており、その次のポインターに初期化されたオブジェクトへのポインターが含まれている場合、問題は何ですか?
前もって感謝します。
c++ - CMPXCHG16Bは正しいですか?
理由はわかりませんが、これは正確には正しくないようです。CMPXCHG16Bのドキュメントはごくわずかなので、アドバイスは素晴らしいでしょう(私はインテルのマニュアルを持っていません...)
例を使用して実行すると、1になるはずのときに0が返されます。何かアイデアはありますか?
memcached - EhCacheでのコンペアアンドスワップ(CAS)の実装
EhCacheでMemCacheのCASMutator.casに相当するものを見つけようとしています。基本的に、EhCacheをMemCacheに交換しており、CASを介して値を設定するためのインターフェイスを実装する必要があります。誰かがこれについて何か洞察を持っていますか?また、私がこれらのいずれかの専門家であるとは主張していないことを考えると、CASが実際にどのように機能するか/それが何をしているのかについての高レベルの概要を誰かが持っているなら、それもありがたいです。
multithreading - コンセンサス値
並行プログラミングを読んでいるときに、コンペア・アンド・スワップおよびコンペア・アンド・セット操作でコンセンサス番号という用語に出くわしました。この用語の意味を理解するのに苦労しています、誰か説明できますか?
ありがとうございました!!
c# - ダブルチェックロックが使用されるのはなぜですか?
二重チェックのロックを使用するコードに出くわし続けていますが、なぜそれが使用されているのか、いまだに混乱しています。
私は最初、ダブルチェック ロックが壊れていることを知りませんでした。それを知ったとき、この疑問が拡大しました。そもそもなぜ人々はそれを使用するのでしょうか? コンペア&スワップの方がいいんじゃない?
(上記のコードは C# 用ですが、私の質問は C# と Java の両方に当てはまります。)
二重チェックのロックには、アトミック操作と比較して、ある種の固有の利点がありますか?
c++ - コンペアアンドスワップアトミック操作とロードリンク/ストア条件付き操作
x86プロセッサでは、コンペアアンドスワップアトミック操作とロードリンク/ストア条件付き操作の違いがわかりません。後者は前者より安全ですか?最初のものが2番目のものよりも優れているというのは本当ですか?