問題タブ [memory-barriers]
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.
c++ - プリエンプティブ マルチタスキングは、C++11 リリース取得セマンティクスに干渉する可能性がありますか?
(理論的には) スレッドが 1 つの CPU で を実行した後、すぐにが実行されなかっacquire
た別の CPU でプリエンプトされて再開される可能性はありますか?acquire
たとえば。C++11 アトミックとrelease-acquire
メモリ順序付けを使用して、ロックのないスレッドセーフな初期化を実行する次のコードを検討してください。
true を返す場合_initFlag.load(memory_order_acquire)
、呼び出し元のスレッドは_foo
、 、 などの初期化された値が現在実行中_bar
の CPU に可視 (伝播) であることを認識します。しかし、スレッドがその直後に横取りされ、別の CPU に移動された場合はどうなるでしょうか?..
C++11 標準は、新しい CPU が同期されることを保証しますか? この種の競合状態に対して脆弱な実装またはアーキテクチャはありますか?
c# - メモリバリアの有無にかかわらず Spinlock.exit
メモリバリアは私にとって新しい概念であるため、理解を深めるために次のテストプログラム (C#) を作成しました。
問題は Spinlock.Exit(true) 関数に関するものです。true は、終了アクションを他のスレッドにすぐに公開するためにメモリ バリアが発行されることを意味します。
false を渡すと、メモリ バリアは発行されず、コードはほぼ 2 倍の速さで実行されます。
アクション オブジェクトがスレッド間の共有メモリを含み、false が渡された場合でも、それは正しいプログラムですか? メモリバリアが非常に遅いのはなぜですか?
c++ - コンパイラバリアの目的は何ですか?
以下は、 Concurrent Programming on windows、Chapter 10 Page 528~529、c++ テンプレートからの抜粋です実装を再確認してください
著者の状態として:
_WriteBarrier は、オブジェクトをインスタンス化した後、m_pValue フィールドにそのオブジェクトへのポインターを書き込む前に見つかりました。これは、オブジェクトの初期化での書き込みが m_pValue 自体への書き込みを超えて遅延しないようにするために必要です。
_WriteBarrier はコンパイル バリアであるため、コンパイルが LeaveCriticalSection のセマンティクスを知っていると便利ではないと思います。コンパイルはおそらく pValue への書き込みを省略しますが、関数呼び出しの前に代入を移動するような最適化は行わないでください。そうしないと、プログラムのセマンティクスに違反します。LeaveCriticalSection には暗黙的なハードウェア フェンスがあると思います。したがって、m_pValue への割り当て前の書き込みはすべて同期されます。
一方、コンパイルが LeaveCriticalSection のセマンティクスを認識していない場合、コンパイルがクリティカル セクションから割り当てを移動するのを防ぐために、すべてのプラットフォームで _WriteBarrier が必要になります。
そして_ReadBarrierについて、著者は言った
同様に、m_value を返す直前に _ReadBarrier が必要です。これにより、getValue の呼び出し後のロードが、呼び出しの前に発生するように並べ替えられません。
まず、この関数がライブラリに含まれていて、ソース コードが利用できない場合、コンパイルはどのようにしてコンパイル バリアがあるかどうかを知るのでしょうか?
第二に、必要に応じて間違った場所に配置される可能性があります。取得フェンスを表現するには、EnterCriticalSection の直後に配置する必要があると思います。上で書いたことと同様に、コンパイルが EnterCriticalSection のセマンティクスを理解するかどうかに依存します。
また、著者は次のようにも述べています。
ただし、X86、Intel64、および AMD64 プロセッサではどちらのフェンスも必要ないことも指摘しておきます。IA64 のような弱いプロセッサが水を濁らせてしまったのは残念です
上記で分析したように、特定のプラットフォームでこれらのバリアが必要な場合は、すべてのプラットフォームでそれらが必要になります。これらのバリアはコンパイルバリアであるため、コンパイルが正しい最適化を実行できることを確認するだけです。一部の関数のセマンティクス。
間違っている場合は修正してください。
もう 1 つの質問ですが、msvc と gcc が同期セマンティクスを理解している関数を指摘する参照はありますか?
更新 1 : 回答によると (m_pValue はクリティカル セクションからアクセスされます)、ここからサンプル コードを実行すると、次のようになります。
- ここで著者が意味しているのは、コンパイル バリア以外のハードウェア フェンスであると思います。次のMSDNからの引用を参照してください。
- ハードウェアフェンスにも暗黙のコンパイルバリア(コンパイルの最適化を無効にする)があると思いますが、その逆はありません(ここを参照してください、cpuフェンスを使用しても並べ替えは表示されませんが、その逆はありません)
バリアはフェンスではありません。バリアはキャッシュ内のすべてに影響することに注意してください。フェンスは単一のキャッシュ ラインに影響します。
どうしても必要な場合を除き、バリアを追加しないでください。フェンスを使用するには、_Interlocked 組み込み関数のいずれかを選択できます。
著者が書いたように、「X86 Intel64 および AMD64 プロセッサではどちらのフェンスも必要ありません」。
まだ質問が残っています。コンパイルは、Enter/Leave クリティカル セクションの呼び出しのセマンティクスを理解していますか? そうでない場合は、次の回答のように最適化を行っている可能性があり、それが悪い動作を引き起こす可能性があります。
ありがとう
linux - Linuxカーネルのメモリバリアはどのように使用されていますか
次のように、カーネル ソース Documentation/memory-barriers.txt に図があります。
介入がなければ、CPU 1 によって発行された書き込みバリアにもかかわらず、CPU 2 は CPU 1 のイベントを事実上ランダムな順序で認識する可能性があります。
書き込みバリアがあるため、わかりません。C = &B が実行されたときにストアが有効になる必要があります。つまり、Ce B が 2 に等しくなったときです。 C は &B ですが、なぜ B を 7 と認識するのでしょうか。私は本当に混乱しています。
c++ - アトミック ルールの緩和の (わずかな) 違いは何ですか?
Herb Suttersの「原子兵器」に関する優れた講演を見た後、 Relaxed Atomicsの例について少し混乱しました。
私は、C++ メモリ モデル(SC-DRF = データ競合のない連続整合性)のアトミックが、ロード/読み取りで「取得」を行うことを理解しました。
std::memory_order_seq_cst
ロード[およびストア]のデフォルトはであるため、2つは同じであることを理解しています。
これまでのところ、Relaxed Atomics は使用されていません (話を聞いた後は、Relaxed Atomics を使用することは決してありません。約束します。しかし、誰かに尋ねられたら、説明する必要があるかもしれません...)。
しかし、なぜ私が使用すると「リラックスした」セマンティクスなのですか
loadはを取得していて解放していないのに、これが(1)
and と異なるのはなぜ(2)
ですか? ここで実際にリラックスしているのは何ですか?
私が考えることができる唯一のことは、loadがacquireを意味すると誤解したことです。そして、それが真であり、デフォルトseq_cst
が両方を意味する場合、それは完全なフェンスを意味するのではないでしょうか? その命令を上に渡すことも、下に移動することもできませんか? 私はその部分を誤解していたに違いありません。
[そしてストアとリリースのために対称的に]。
c++ - C++「メモリバリア」の例
volatile キーワードに関するこの質問への回答を読んでいました。
https://stackoverflow.com/a/2485177/997112
その人はこう言います。
並べ替えを防止する解決策は、メモリ バリアを使用することです。これは、コンパイラと CPU の両方に対して、この時点でメモリ アクセスを並べ替えることができないことを示します。volatile 変数アクセスの周りにこのようなバリアを配置することで、non-volatile アクセスでさえも volatile アクセスを介して並べ替えられないことが保証され、スレッド セーフなコードを記述できるようになります。
ただし、メモリバリアは、バリアに到達したときに保留中のすべての読み取り/書き込みが実行されることも保証するため、必要なものすべてを効果的に提供し、volatile を不要にします。volatile 修飾子を完全に削除するだけです。
この「メモリバリア」はC++でどのように実装されていますか?
編集:
誰かが簡単なコード例を教えてください。