問題タブ [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.
concurrency - メモリーフェンスとは?
明示的なメモリ フェンスを使用するとはどういう意味ですか?
multithreading - AtomicInstructionsとVariableUpdateの可視性
最も一般的なプラットフォーム(最も重要なのはx86です。一部のプラットフォームには、マルチスレッドに役立つ保証がほとんどない非常に難しいメモリモデルがあることを理解していますが、まれな反例は気にしません)、次のコードは安全ですか?
スレッド1:
スレッド2:
アトミック操作の標準的で合理的な実装を想定すると、次のようになります。
- スレッド1の割り当ては、呼び出される
someVariable
前に完了することが保証されていますか?atomicSet()
- スレッド2は、アトミックに読み取る場合、
someVariable
呼び出す前に割り当てを確認することが保証されていますか?doMoreStuff()
stuffDoneFlag
編集:
- 私が使用しているアトミック操作の実装には
LOCK
、役立つ場合は、各操作にx86命令が含まれています。 stuffDoneFlag
なんとかして適切にクリアされたと仮定します。どのように重要ではありません。- これは非常に単純化された例です。問題のコンテキスト全体を理解して答える必要がないように、この方法で作成しました。私はそれが効率的ではないことを知っています。
.net - .NET メモリ モデル、揮発性変数、およびテスト アンド セット: 何が保証されていますか?
.NET メモリ モデル (.NET Framework 上。compact/micro/silverlight/mono/xna/what-have-you ではない) では、特定の型 (特にプリミティブ整数と参照) の操作が保証されていることを知っています。アトミック。
さらに、x86/x64 の test-and-set 命令 (およびInterlocked.CompareExchange
) は実際にはグローバル メモリの場所を参照しているため、成功すると別の命令Interlocked.CompareExchange
が新しい値を参照することになると思います。
最後に、volatile
キーワードは、読み取りと書き込みをできるだけ早く伝達し、この変数に関する操作の順序を変更しないようにするためのコンパイラへの指示であると思います (右?)。
これにより、いくつかの疑問が生じます。
- 上記の私の信念は正しいですか?
Interlocked.Read
int のオーバーロードはなく、long (2 つの WORD であるため、通常はアトミックに読み取られません) のみです。.NET メモリ モデルでは、整数/参照を読み取るときに最新の値が表示されることが保証されていると常に想定していましたが、プロセッサ キャッシュやレジスタなどを使用すると、これが不可能になる可能性があることがわかり始めています。変数を強制的に再フェッチする方法はありますか?- volatile は、整数と参照に関する上記の問題を解決するのに十分ですか?
- x86/x64では、それを想定できます...
2 つのグローバル整数変数 x と y があり、どちらも 0 に初期化されている場合、次のように記述します。
その NO スレッドは、x = 0 および y = 2 を認識します (つまり、書き込みは順番に発生します)。それらが揮発性である場合、これは変わりますか?
c++ - メモリ フェンス - 理解するのに助けが必要
Paul E. McKenney の Memory Barriers を読ん でいます。私は、すべてを無意味にし、何も理解していないと思わせる一文に出くわします。例を示しましょう
この 2 つの関数が異なるプロセッサで実行されているとします。ここで、最初のプロセッサが「a」へのストアをキューに格納し、b 命令のストアに進むため、2 番目のプロセッサによる b #2 へのストアの後に、a #1 へのストアが表示される可能性があります。OK、問題ありません。#1 と #2 の間の行に書き込みフェンスを追加しますが、このコードはまだ失敗する可能性があります。これは、2 番目のプロセッサが無効化メッセージをキューに入れる可能性があるためです。 #4 と #4 の間の線。
これにより、2 番目のプロセッサがキューに入れられたすべてのメッセージを処理し (a を無効化)、#4 の最初のプロセッサに read MESI メッセージを送信して再度読み取るようになります。わかった。次に記事は言う
そのため、多くの CPU アーキテクチャは、これら 2 つのいずれか一方のみを実行する、より弱いメモリ バリア命令を提供します。大まかに言えば、「読み取りメモリ バリア」は無効キューのみをマークし、「書き込みメモリ バリア」はストア バッファのみをマークします。本格的なメモリバリアは両方を行います。
素晴らしい、それは明らかですが、その後、私はこれを見ます
この結果、読み取りメモリ バリアは、それを実行する CPU でのみロードを命令するため、読み取りメモリ バリアに先行するすべてのロードは、読み取りメモリ バリアに続くすべてのロードの前に完了したように見えます。同様に、書き込みメモリ バリアは、書き込みメモリ バリアの前にあるすべてのストアが、書き込みメモリ バリアに続くストアの前に完了したように見えるように、ストアを実行する CPU でのみストアを注文します。
それで
読み取りメモリ バリアに先行するすべてのロードは、読み取りメモリ バリアに続くすべてのロードの前に完了したように見えます。
それは、前に説明したことすべてを混同します。どういう意味ですか?"a" #4 のロードの前に、関数 "bar" のどのロードを完了する必要がありますか? オブジェクト「a」が配置されているキャッシュラインを無効にすることができなかったため、プロセッサが古い値を読み取る可能性があるという理由だけで、この関数のメモリバリアなしでアサートが失敗する可能性があることを理解しています。
詳細な説明は本当に役に立ちます。私は一日中理解しようとしています。
よろしくお願いします。
c++ - メモリ順序の問題
私は C++0x のサポートを試していますが、あるべきではないと思われる問題があります。主題が理解できないか、gcc にバグがあります。
最初は次のコードがx
あり、y
等しいです。スレッド 1 は常にx
最初にインクリメントし、次にインクリメントしますy
。どちらもアトミックな整数値なので、インクリメントはまったく問題ありません。スレッド 2 はx
がより小さいかどうかをチェックy
し、そうであればエラー メッセージを表示します。
このコードは時々失敗しますが、なぜですか? ここでの問題はおそらくメモリの並べ替えですが、すべてのアトミック操作はデフォルトで順次一貫しており、これらの操作を明示的に緩和しませんでした。このコードを x86 でコンパイルしていますが、私が知る限り、順序付けの問題はありません。何が問題なのか説明してもらえますか?
結果はこちらでご覧いただけます。
c++ - 取得と解放のペアの順不同の実行
アトミック変数が取得と解放のペアで古い値をロードできるかどうかを考えています。アトミック変数 x があり、その変数を解放セマンティクスで格納し、後で取得セマンティクスでロードするとします。理論上、古い値を読み取ることは可能ですか?
スレッド 2 が x をロードしたときに関数スレッド 1 が終了した場合 (したがって、新しい値が格納されます)、スレッド 2 が x から古い値をロードすることは可能ですか? 言い換えれば、ロードの前に x への実際のストアが行われた場合、アサートが発生する可能性はありますか?
インターネットの記事から理解した限りでは可能ですが、その理由はわかりません。x へのストアによって生成されるメモリ フェンスはストア バッファを空にすることを保証しますが、x からのロードでのメモリ フェンスの取得はキャッシュ ラインを無効にすることが保証されるため、最新の値を読み取る必要があります。
追加した
acquire-release 自体には強制的な順序付けがないということですか? リリース前に行われたことはすべてリリース前に行われ、取得後に行われたことはすべてその後に行われるため、取得とリリースのペアは他の操作で順序付けを強制します (なぜ??)。私はそれを正しく理解しましたか?コードでは、次のアサートが発火しないことが保証されているということですか
もちろん、スレッド1がすでにストアを終了している場合も同様です。x.load を while (x.load() == 0) に置き換えると、これは 100% 機能しますが、これが機能する原因はわかりません。
そして、コードを次のコードに置き換えるとどうなりますか
それは何かを変えますか?
ありがとう。
assembly - Intel 64 および IA-32 | セマンティックの取得/解放を含むアトミック操作
Intel 64 and IA-32 Architectures Software Developer's Manual によると、LOCK シグナル プレフィックスは、「シグナルがアサートされている間、プロセッサが共有メモリを排他的に使用することを保証します」。これは、バス ロックまたはキャッシュ ロックの形式である場合があります。
しかし、それが私がこの質問をしている理由です-このプレフィックスがメモリバリアも提供するかどうかは私には明らかではありません.
マルチプロセッサ環境で NASM を使用して開発しており、オプションの取得および/または解放セマンティクスを使用してアトミック操作を実装する必要があります。
では、MFENCE、SFENCE、および LFENCE 命令を使用する必要がありますか、それとも冗長でしょうか?
c++ - Visual C++ x86 での volatile 変数とアトミック操作
プレーン ロードは x86 で取得セマンティクスを持ち、プレーン ストアはリリース セマンティクスを持ちますが、コンパイラは命令を並べ替えることができます。フェンスとロックされた命令 (ロックされた xchg、ロックされた cmpxchg) は、ハードウェアとコンパイラの両方の並べ替えを防ぎますが、コンパイラのバリアで保護するために、プレーンなロードとストアは依然として必要です。Visual C++ には、コンパイラの並べ替えを防ぐ _ReadWriterBarrier() 関数が用意されています。また、C++ には、同じ理由で volatile キーワードが用意されています。私は、すべてが正しいことを確認するためだけに、このすべての情報を書きます。上に書かれていることはすべて真実です。_ReadWriteBarrier() で保護された関数で使用される揮発性変数としてマークする理由はありますか?
例えば:
その変数を非揮発性にしても安全ですか? 私が理解している限り、関数は保護されており、内部のコンパイラーによって並べ替えを行うことができないためです。一方、Visual C++ は volatile 変数に特別な動作を提供し (標準が行うものとは異なります)、揮発性の読み取りと書き込みをアトミックなロードとストアにしますが、私のターゲットは x86 であり、単純なロードとストアは x86 でアトミックであると想定されています。とにかく、ですよね?
前もって感謝します。
c++ - フェンス、アプリケーション、サポートするチップのないC ++ 0X memory_order
前の質問のフォローアップとして、クラスatomic<T>
はmemory_order
パラメーターを使用してほとんどの操作を指定します。フェンスとは対照的に、このメモリ順序は、それが動作するアトミックにのみ影響します。おそらく、そのようないくつかのアトミックを使用することで、他のメモリの順序が重要でない並行アルゴリズムを構築できます。
だから私は2つの質問があります:
- 誰かが私に、個々のアトミック変数の順序付けから利益を得て、フェンスを必要としないアルゴリズム/状況の例を指摘できますか?
- このタイプの動作をサポートする最新のプロセッサはどれですか?つまり、コンパイラが特定の順序を通常のフェンスに変換するだけではありません。