19

std::atomicやなどの関数は引数storeload取りstd::memory_orderます。引数は、他の関数の引数と同様に、実行時に決定できます。ただし、実際の値は、コンパイル中のコードの最適化に影響を与える可能性があります。次の点を考慮してください。

std::atomic<int> ai1, ai2;
int value = whatever;

void foo() {
    std::memory_order memOrd = getMemoryOrder();
    register int v = value; // load value from memory
    ai1.store(v, memOrd);   // dependency on v's value
    ai2.store(1, memOrd);   // no dependency. could this be move up?
}

である場合memOrdmemory_order_relaxed2 番目の店舗は最初の店舗の前に安全に移動できます。これにより、読み込みと使用の間に余分な作業が追加さvalueれ、それ以外の場合に必要なストールが防止される可能性があります。ただし、memOrdisの場合memory_order_seq_cst、ストアの切り替えは許可されません。これは、 is が 1 に設定されている場合に、他のスレッドがai1すでに に設定されていると見なす可能性があるためです。valueai2

私が疑問に思っているのは、メモリの順序がコンパイル時ではなくランタイム引数として定義された理由です。最適なメモリ操作のセマンティクスを決定する前に、誰かが実行時に環境を調べる理由はありますか?

4

3 に答える 3

8

これがコンパイル時パラメーターではなく実行時パラメーターとして実装される理由は、合成を可能にするためです。

提供されたアトミック操作を使用してロード操作と同等の操作を行うが、より高いレベルの構造で操作する関数を作成しているとします。メモリ順序を実行時パラメータとして指定することで、高レベルのロードは、ユーザーが指定したメモリ順序パラメータを、順序を提供するために必要な低レベルのアトミック操作に渡すことができます。高レベルの操作がテンプレートである必要はありません。

通常、アトミック命令はインラインであり、実際にコンパイル時の定数である場合、コンパイラはメモリ順序パラメーターのテストを排除します。

于 2012-12-19T07:52:09.063 に答える
4

を実行時に指定できるようにする単なるインターフェース仕様です。memory_order実装でその許可を使用する必要はありません。

たとえば、x86 ハードウェアmemory_order_seq_cstでは、何を指定しても、おそらく得られるものです。memory_order_relaxedハードウェア キャッシュ コヒーレンシ プロトコルが原因で利用できません。

コンパイル時の既知の順序を最適化できる可能性がある他のハードウェアでは、実装によって、既定のパラメーターを利用する追加のオーバーロードが提供される場合があります。

于 2012-12-18T22:28:24.757 に答える