3

Anthony Williams によるC++ Concurrency in Actionを読んでいます。現在、私は彼がmemory_order_consumeについて説明している時点で.

そのブロックの後にあります:

メモリの順序付けの基本について説明したので、次はより複雑な部分を見ていきます。

私はいくつかのことを完全には理解していないので、少し怖いです:


dependency-ordered-before とsynchronizes-with の違いは? どちらも事前発生関係を作成します。正確な違いは何ですか?


次の例について混乱しています:

int global_data[]={ … };
std::atomic<int> index;
void f()
{
    int i=index.load(std::memory_order_consume);
    do_something_with(global_data[std::kill_dependency(i)]);
}

kill_dependency は正確に何をしますか? それはどの依存関係を殺しますか?どのエンティティ間で? そして、コンパイラはその知識をどのように活用できるのでしょうか?


memory_order_consume のすべての発生を安全に memory_order_acquire に置き換えることができますか? つまり、あらゆる意味でより厳格ですか?


リスト 5.9 で、安全に置き換えることができますか?

std::atomic<int> data[5]; // all accesses are relaxed

int data[5]

? つまり、取得と解放を使用して、非アトミック データへのアクセスを同期できますか?


彼は、キュービクルにいる男性を例に、リラックス、取得、解放について説明しています。seq_cst と consumer の同様の簡単な説明はありますか?

4

3 に答える 3

4

最後から 2 番目の質問については、もう少し説明が必要です。複数のスレッドが同じデータにアクセスする場合、次の 3 つの問題が発生する可能性があります。

  1. システムは、読み取りまたは書き込みの途中でスレッドを切り替え、半分が 1 つの値で半分が別の値になる結果を生成する可能性があります。

  2. コンパイラは、関連するデータを参照しているスレッドが他にないという前提で、コードを移動する可能性があります。

  3. プロセッサは、値を変更した後にメインメモリを更新したり、別のスレッドがメインメモリの値を変更した後に再度読み取ったりすることなく、ローカルキャッシュに値を保持している可能性があります。

メモリ順序のアドレスは 3 番のみです。アトミック関数は 1 と 2 をアドレス指定し、メモリ順序の引数によっては 3 もアドレス指定します。したがって、memory_order_relaxed は、「番号 3 を気にしないでください。コードは引き続き 1 と 2 を処理します。その場合、acquire と release を使用して適切なメモリ順序を確保します。

于 2013-02-08T19:24:01.860 に答える
2

dependency-ordered-before とsynchronizes-with の違いは?

1.10/10 より: "[ 注: 「依存関係が前に順序付けられている」という関係は、「と同期する」に似ていますが、解放/取得の代わりに解放/消費を使用します。

kill_dependency は正確に何をしますか?

一部のコンパイラは、データ依存性分析を行います。つまり、何を同期する必要があるかをよりよく把握するために、変数の値の変更を追跡します。kill_dependencyコンパイラが理解できないことがコード内で起こっているため、そのようなコンパイラにこれ以上トレースしないように指示します。

memory_order_consume のすべての発生を安全に memory_order_acquire に置き換えることができますか? つまり、あらゆる意味でより厳格ですか?

と思いますが、定かではありません。

于 2013-02-08T19:17:22.143 に答える
2

memory_order_consume では、データに依存するすべての非アトミック操作の前に、アトミック操作が発生する必要があります。データの依存関係は、そのデータを使用しないと式を評価できない依存関係です。たとえば、x->y では、最初に x を評価せずに x->y を評価する方法はありません。

kill_dependency は独自の関数です。他のすべての関数は、引数にデータ依存性があります。Kill_dependency は明示的にそうしません。データ自体は既に同期されていることがわかっている場合に表示されますが、データを取得するために必要な式は同期されていない可能性があります。あなたの例では、do_something_with は globalldata[i] のキャッシュされた値を安全に使用できると想定できますが、i 自体は実際には正しい原子値でなければなりません。

データへのすべての変更が一致する memory_order_release で適切にリリースされる場合、 memory_order_acquire は厳密に強力です。

于 2013-09-04T04:20:26.190 に答える