問題タブ [memory-fences]
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++0x 同時同期、フェンスが必要か
最近、アトミックと C++0x についていくつか質問しました。コードを変換する前に、順序付けのセマンティクスを理解しておきたいと思います。このプレ0xコードがあるとしましょう:
現在のコンパイラ/プラットフォームがatomic_int
、atomic_store_fence
およびに提供するものを使用しますatomic_load_fence
。
C++0x では、コードにはいくつかの可能な形式があります。2つの明白なものは次のように見えます:
また
アトミックなストアリリース/ロード取得シーケンスは、明示的なフェンスバージョンと同じメモリ順序の意味を持つ同期イベントであると読んで正しいですか? つまり、2番目のバージョンは正しいですか?
正しければ、2 番目のものは必要以上にフェンスを発行しますa != 1
。標準のセクション 29.8-3 は、アトミックとフェンスを組み合わせて使用できることを示しています。それでは、以下は正しく合理的な実装ですか?
multithreading - __faststorefenceの動作は何ですか?
この質問に関しては、x86とx86-64にのみ興味があります。
MSVC 2005の場合、__ faststorefenceのドキュメントには、「先行するすべてのストアが後続のストアの前にグローバルに表示されることが保証されます」と記載されています。
MSVC 2008および2010では、次のように変更されました。 「ロードメモリ参照とストアメモリ参照の両方を含む、以前のすべてのメモリ参照が、後続のメモリ参照の前にグローバルに表示されることを保証します。」
後者の書き方は、私の意見では、これは古いストアの前にCPUがロードを並べ替えることもブロックすることを意味します。これは最初の定義とは異なります。つまり、本質的には、非一時ストアと古いストアのブロックまたは並べ替えのみを処理することです(他の唯一の並べ替えx86(-64)は処理します)。
ただし、ドキュメントは矛盾しているように見えます。「x64プラットフォームでは、このルーチンはsfence命令よりも高速なストアフェンスである命令を生成します。x64プラットフォームでは_mm_sfenceの代わりにこの組み込み型を使用してください。」
これは、それがまだsfenceのような機能を持っていることを意味し、したがって、ロードはまだ古いストアで並べ替えることができます。それで、それはどれですか?誰かが私の混乱を解消できますか?
PS:この関数のGCCバージョンを探していて、出くわしましlong local; __asm__ __volatile__("lock; orl $0, %0;" : : "m"(local));
たが、32ビットコードからのものだと思います。64ビットアナログは何でしょうか?
c++ - 揮発性の読み取りと書き込みは、Windows + VisualC でアトミックですか?
このサイトにはvolatile
、アトミック/マルチスレッド アクセスに変数を使用できるかどうかを尋ねる質問がいくつかあります。たとえば、ここ、ここ、またはここを参照してください。
さて、C(++) 標準準拠の答えは明らかにnoです。
ただし、Windows および Visual C++ コンパイラでは、状況はそれほど明確ではないようです。
私は最近、 MSDNの公式ドキュメントに回答して引用しましたvolatile
マイクロソフト固有
volatile として宣言されたオブジェクトは (...)
- 揮発性オブジェクトへの書き込み (揮発性書き込み) にはリリース セマンティクスがあります。グローバルまたは静的オブジェクトへの参照? 命令シーケンスで揮発性オブジェクトへの書き込みが発生する前に、コンパイルされたバイナリで揮発性書き込みが発生する前に発生します。
- 揮発性オブジェクトの読み取り (揮発性読み取り) には、取得セマンティクスがあります。グローバルまたは静的オブジェクトへの参照 ? これは、命令シーケンスで揮発性メモリの読み取り後に発生するものであり、コンパイルされたバイナリでの揮発性読み取りの後に発生します。
これにより、揮発性オブジェクトをマルチスレッド アプリケーションでのメモリのロックと解放に使用できます。
[鉱山を強調]
さて、これを読むと、揮発性変数はstd::atomic
、今後の C++11 標準と同様に、MS コンパイラによって処理されるように思われます。
しかし、私の回答へのコメントで、ユーザーHans Passantは次のように書いています。
注: MSDN に示されている例はかなり怪しいように見えます。通常、atomic exchangeなしではロックを実装できないためです。(アレックスも指摘したように。)これはまだ疑問を残しています。この MSDN の記事に記載されている他の情報の有効性、特にhereおよびhereのようなユース ケースの妥当性に注意してください。)
さらに、The Interlocked* 関数のドキュメントがあり、特にvolatile(!?)InterlockedExchange
変数を取り、アトミックな読み取りと書き込みを行います。(SO に関する 1 つの質問 -- InterlockedExchange をいつ使用する必要がありますか? -- は、この機能が読み取り専用または書き込み専用のアトミック アクセスに必要かどうかについて正式に回答していないことに注意してください。)
さらに、volatile
上記のドキュメントは「グローバルまたは静的オブジェクト」を何らかの形でほのめかしており、「実際の」取得/解放セマンティクスがすべての値に適用されるべきだと私は考えていました。
質問に戻る
Windows では、Visual C++ (2005 - 2010) を使用して、(32bit? int?) 変数を宣言するvolatile
と、この変数へのアトミックな読み取りと書き込みが許可されますか?
私にとって特に重要なことは、プログラムが実行されるプロセッサやプラットフォームとは関係なく、これが Windows/ VC ++ で保持される (または保持されない) ことです。(つまり、それが WinXP/32bit であるか、Itanum2 で実行されている Windows 2008R2/64bit であるかは重要ですか?)
検証可能な情報、リンク、テストケースで回答をバックアップしてください!
c - アウト オブ オーダー実行とメモリ フェンス
最新の CPU が順不同で実行できることは知っていますが、ウィキペディアで説明されているように、常に結果を順番どおりに破棄します。
「順不同のプロセッサは、これらの「スロット」を、準備ができている他の命令で時間内に埋め、最後に結果を並べ替えて、命令が通常どおりに処理されたように見せます。」
現在、マルチコア プラットフォームを使用する場合はメモリ フェンスが必要であると言われています。これは、アウト オブ オーダーの実行により、xの間違った値がここに出力される可能性があるためです。
ここで私の質問は、アウト オブ オーダー プロセッサ (私が想定するマルチコア プロセッサの場合はコア) は常に結果をイン オーダーで破棄するため、メモリ フェンスの必要性は何かということです。マルチコア プロセッサのコアは、他のコアからのリタイアした結果のみを認識しますか?それとも処理中の結果も認識しますか?
上記の例では、プロセッサ 2 が最終的に結果を破棄するとき、xの結果はfの前に来るはずですよね? 順不同の実行中に、 x の前に f を変更した可能性がありますが、 x の前にそれを廃止してはならないことはわかっていますよね?
結果のインオーダー リタイアとキャッシュ コヒーレンス メカニズムが整った今、なぜ x86 でメモリ フェンスが必要になるのでしょうか?
opencl - OpenCL では、バリア() とは対照的に、mem_fence() は何をしますか?
barrier()
(私は理解していると思います) とは異なりmem_fence()
、ワーク グループ内のすべての項目に影響を与えるわけではありません。OpenCL の仕様には、(セクション 6.11.10) と記載されていmem_fence()
ます。
カーネルを実行するワークアイテムのロードとストアを命令します。
(したがって、単一の作業項目に適用されます)。
しかし、同時に、セクション 3.3.1 では次のように述べています。
ワークアイテム メモリ内では、ロード/ストアの一貫性があります。
そのため、作業項目内でメモリは一貫しています。
では、どんなことにmem_fence()
役立つのでしょうか。アイテム間では機能しませんが、アイテム内では必要ありません...
アトミック操作を使用していないことに注意してください (セクション 9.5 など)。mem_fence()
それらと組み合わせて使用するという考え方ですか?もしそうなら、私は例を見てみたいです。
ありがとう。
更新: で使用すると どのように役立つかがわかりますbarrier()
(暗黙的に、バリアが呼び出すためmem_fence()
) - しかし、それは別々に存在するので、確かにもっとあるはずですか?
c++ - xchg を使用する場合、mfence は必要ですか?
セットおよびテストxchg
ベースのアセンブリ ロックがあります。私の質問は:
命令を使用する場合、メモリフェンシング ( mfence
、sfence
またはlfence
)を使用する必要がありxchg
ますか?
編集 :
64 ビット プラットフォーム: Intel nehalem を使用
c++ - C++ プログラムで電気柵を使用する
最近、Electric Fence を試していますが、C++ コードでの使用方法がわかりません。
次に例を示します。
でコンパイルしました
また、最初に Electric Fence バナーが表示されず、実行可能ファイルに EF シンボルが見つかりません (nm コマンドを使用)。
しかし、プログラムを次のように変更すると:
すべてが良好です-EFが表示されます。私はそれが問題をちょっと解決することを知っています、私は知っています:)。そもそもなぜ機能しなかったのかを理解しnew()
たいmalloc()
だけdelete()
ですfree()
。
私がこれに参加した理由は、boostライブラリやその他のいくつかを使用する大きなプロジェクトです。そして、このプログラムはmalloc()
orfree()
を直接呼び出すことはありません。そして、EFでビルドするときは、EFを最終的な実行可能ファイルにリンクするだけでなく、EFをそれらにリンクしようとするすべてのライブラリを再構築しました。そして、どちらにもEFシンボルが見つかりません。それは正しいアプローチですか?それとも間違っていて、最終的にEFのみを実行可能ファイルにリンクする必要があり、ライブラリはそのままにしておく必要がありますか? しかし、実行可能ファイルに EF シンボルが見つかりません。
c++ - std::call_once とメモリの並べ替え
ここからのコードを考えると:
また、別の場所でも同じパターンのバリエーションをいくつか見ました。私の質問は、なぜこのコードが保存されていると見なされるのですか? なぜコンパイラはstd::call_once を呼び出す前にデータを読み取ることができず、間違ったデータになってしまうのでしょうか? 例えば
つまり、それを妨げる障壁については何も見つけていません。
multithreading - スーパーバイザーワーカーモデルでメモリフェンスを使用する必要がありますか?
アプリケーションのマルチスレッド サポートを構築しています。
私のアプリケーションでは、ワーカーが別のワーカーの「作業フィールド」にアクセスして、自分のジョブを完了する必要がある場合があります。pthread ミューテックスを使用してこれを安全にしようとしましたが、ワーカーが 1 つしかなく競合がない場合でも、非常に遅いことが判明しました。
そこで、私は別のアイデアを思いつきました。ワーカーにジョブを可能な限り完了させてから、(ワーカーごとの、独自の) キューに前述の問題のあるジョブを追加します。すべてのワーカーが完了すると、メイン スーパーバイザー スレッドが未完了のジョブを完了します。それらが労働者によって行われた仕事の数よりも桁違いに少ないことを願っています.
私の質問は、実行をスーパーバイザーからワーカーに、またはその逆に転送するときに、メモリ フェンスを投入する必要があるかどうかです。
編集: 詳細 (コードはgithubにあります。pool::collision_wsc() を参照してください)。各スレッドは、さまざまな「セル」(基本的には std::vector) からポインターを読み取り、ポイントされたオブジェクトに何らかの操作を適用します (ハード球間の衝突)。
要点は、セルは隣接するセル (の一部) と相互作用しますが、これらのセルの一部は別のワーカーの所有物である可能性があります (1 つの球がセルの境界近くにあり、別のセルの 1 つと衝突する可能性があります)。
synchronization - pthreadミューテックスに関連する完全なメモリバリアに関する説明
ミューテックスを処理する場合、必要なメモリバリアはpthreadAPI自体によって処理されると聞いています。この件についてもっと詳しく知りたいのですが。
- これらの主張は、少なくとも周りの最も一般的なアーキテクチャでは真実ですか?
- コンパイラはこの暗黙の障壁を認識し、コードを生成するときに操作の並べ替え/ローカルレジスタからの読み取りを回避しますか?
- メモリバリアはいつ適用されますか:ミューテックスを正常に取得した後、およびそれを解放した後?