web-dev-qa-db-ja.com

std :: atomic | compare_exchange_weakとcompare_exchange_strong

私が理解していないのか、ドキュメントが明確に作成されていないのかはわかりません。

次の抜粋は、最新のドラフト(N3126、セクション29.6)から抜粋したものです。

bool atomic_compare_exchange_weak(volatile A* object, C * expected, C desired);
bool atomic_compare_exchange_weak(A* object, C * expected, C desired);
bool atomic_compare_exchange_strong(volatile A* object, C * expected, C desired);
bool atomic_compare_exchange_strong(A* object, C * expected, C desired);
bool atomic_compare_exchange_weak_explicit(volatile A* object, C * expected, C desired, memory_order success, memory_order failure);
bool atomic_compare_exchange_weak_explicit(A* object, C * expected, C desired, memory_order success, memory_order failure);
bool atomic_compare_exchange_strong_explicit(volatile A* object, C * expected, C desired, memory_order success, memory_order failure);
bool atomic_compare_exchange_strong_explicit(A* object, C * expected, C desired, memory_order success, memory_order failure);
bool A::compare_exchange_weak(C & expected, C desired, memory_order success, memory_order failure) volatile;
bool A::compare_exchange_weak(C & expected, C desired, memory_order success, memory_order failure);
bool A::compare_exchange_strong(C & expected, C desired, memory_order success, memory_order failure) volatile;
bool A::compare_exchange_strong(C & expected, C desired, memory_order success, memory_order failure);
bool A::compare_exchange_weak(C & expected, C desired, memory_order order = memory_order_seq_cst) volatile;
bool A::compare_exchange_weak(C & expected, C desired, memory_order order = memory_order_seq_cst);
bool A::compare_exchange_strong(C & expected, C desired, memory_order order = memory_order_seq_cst) volatile;
bool A::compare_exchange_strong(C & expected, C desired, memory_order order = memory_order_seq_cst);

備考:弱い比較と交換の操作は誤って失敗する可能性があります。つまり、操作の前にexpectedが指すメモリの内容がオブジェクトの内容と同じで、その後のexpectedの内容と同じである間、falseを返します。操作。 [注:この偽の障害により、ロードロックされたストア条件付きマシンなど、より広範なクラスのマシンでの比較および交換の実装が可能になります。スプリアス障害の結果として、弱い比較および交換のほぼすべての使用がループになります。

これはどういう意味ですか?

まず、「誤って失敗する可能性がありますか?!なぜ失敗するのでしょうか?そして、彼らはどのように「かもしれない」を定義しますか?

第二に、「_ strong」と「_weak」という接尾辞を持つ関数の違いが何であるか、私にはまだわかりません。誰かが違いを説明できますか?

編集:それは私がlibstdc ++で見つけたものです-実装(atomic_0.h):

bool compare_exchange_weak(
    __integral_type& __i1,
    __integral_type __i2,
    memory_order __m1,
    memory_order __m2
)
{
    __glibcxx_assert(__m2 != memory_order_release);
    __glibcxx_assert(__m2 != memory_order_acq_rel);
    __glibcxx_assert(__m2 <= __m1);
    return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1);
}

bool compare_exchange_strong(
    __integral_type& __i1,
    __integral_type __i2,
    memory_order __m1,
    memory_order __m2
)
{
    __glibcxx_assert(__m2 != memory_order_release);
    __glibcxx_assert(__m2 != memory_order_acq_rel);
    __glibcxx_assert(__m2 <= __m1);
    return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1);
}
31
0xbadf00d

これは、ハードウェアが実装する共有メモリ整合性モデルに関係しています。ある種の緩和された整合性モデル(リリースセマンティクスなど)を実装するハードウェアアーキテクチャの場合、上記で参照した強力な操作はオーバーヘッドが高くなる可能性があるため、専門家は弱い形式を使用して、緩和された整合性でも適切に機能するアルゴリズムを実装できます。アーキテクチャ。

詳細については、例を参照してください。

http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-95-7.pdf

http://kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.html の第12章と付録C

11
janneb

LL/SC アーキテクチャを参照して、メモは手がかりを与えます。ウィキペディアの記事から:

更新が発生した場合、ロードリンクによって読み取られた値が復元されたとしても、store-conditionalは失敗することが保証されます。そのため、LL/SCペアは、読み取りとそれに続くコンペアアンドスワップ(CAS)よりも強力であり、古い値が復元された場合は更新を検出しません(ABA問題を参照)。

問題のメモリ位置への同時更新がない場合、LL/SCの実際の実装は常に成功するとは限りません。コンテキストスイッチ、別のロードリンク、または(多くのプラットフォームでは)別のロードまたはストア操作など、2つの操作間の例外的なイベントが発生すると、ストア条件が誤って失敗します。

LL/SCチップでは、compare_exchangeはLL/SCの観点から実装されるため、誤って失敗する可能性があるため、失敗した場合にcompare_exchange_strongを再試行するには、追加のオーバーヘッドが必要です。 compare_exchange_strongcompare_exchange_weakの両方を提供することで、プログラマーは、ライブラリーに偽の障害を処理させたいかどうかを決定できます(この場合、compare_exchange_strongを使用するか、それとも自分で処理したいかコード(この場合、compare_exchange_weakを使用します)

31
Jonathan Wakely