問題タブ [memory-model]
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++ - x86 アーキテクチャでのメモリ順序の制限
Anthony Williams は、著書「C++ Concurrency in Action」の中で次のように書いています (309 ページ)。
たとえば、x86 および x86-64 アーキテクチャでは、タグ付けされた memory_order_relaxed または memory_order_seq_cst に関係なく、アトミック ロード操作は常に同じです (セクション 5.3.3 を参照)。つまり、緩和されたメモリー順序付けを使用して記述されたコードは、x86 アーキテクチャーのシステムでは機能する可能性がありますが、SPARC などのより粒度の細かいメモリー順序付け命令セットを使用するシステムでは失敗します。
x86 アーキテクチャではすべてのアトミック ロード操作がmemory_order_seq_cst
. さらに、cppreference std::memory_order
サイトでは、x86 では release-aquire の順序付けが自動であると記載されています。
この制限が有効な場合、順序付けはコンパイラの最適化に適用されますか?
.net - CPU メモリ モデルについてコードでどのような仮定を作成する必要がありますか?また、そのような仮定をどのように文書化する必要がありますか?
私が読んだことによると、Intel プロセッサ アーキテクチャは、.net 実装が提供する必要があるよりも強力なメモリ モデルを強制します。コードが Intel プロセッサの保証をどの程度利用するのが適切か、またはコードがより弱いプロセッサを備えたプラットフォームに移行された場合に備えて、Intel の実装には必要のないメモリ バリアをコードがどの程度追加する必要があるか。メモリモデル? 「弱いメモリモデルを使用している場合にメモリバリアを実行する」などのメソッドを使用して静的クラスを定義し、必要に応じてそのライブラリの「強いモデル」または「弱いモデル」バージョンのいずれかにコードをリンクすることを要求するのは適切でしょうか? あるいは、リフレクションを使用して、プログラムの起動時にそのような静的クラスを生成することもできます。これにより、強力なモデルを使用する場合に JIT コンパイラが「
MemoryLock
ドラザーがいる場合、.net は、セミロックを保持するすべてのスレッドがそのセミロックのメモリモデルに従う必要があるいくつかのセミロック操作を備えたクラスのバリエーションを提供します。非常に強力なメモリ モデルを持つシステムでは、セミロックは何もしません。メモリ モデルが非常に弱いシステムでは、既に別のスレッドが含まれているセミロックに入ろうとするスレッドは、最初のスレッドが終了するか、CPU またはコア (ベース) でスケジュールされるまで待機する必要があります。最初のスレッドが使用していたセミロックで指定されたモデルに基づいて)。通常のロックとは異なり、MemoryLock
すべてのスレッドを同じ CPU で実行するようにスケジュールすることで、競合するロック要件の組み合わせを解決でき、システムは停止したスレッドによって保持されているものを解放できるため、デッドロックが発生することはありません(リソースへのアクセスを保護することがMemoryLock
目的であるため) 。MemoryLock
メモリモデルに違反する方法で、デッドスレッドはもちろんそのようなアクセスを行うことはできません)。
もちろん、.net 4.0 の時点ではそのようなものは存在しません。それを考えると、存在する状況を処理する最善の方法は何ですか? より強力なメモリ モデル用に設計されたコードをより弱いモデルのシステムに移行することは、より強力なモデルを強制する何らかの手段がない場合、災害のレシピとなりますが、多くのLock
またはMemoryBarrier
コードの元のターゲット プラットフォームにとって不要な呼び出しは、あまり魅力的ではないようです。私が知っているコードで強力なメモリ モデルを強制する唯一の方法は、各スレッドに CPU アフィニティを設定させることです。.net が一度に 1 つのコアのみを使用するようにプロセス オプションを設定する方法があれば、それは役立つかもしれません (特に、JIT がバス ロックのインターロック操作をより高速な非バス ロックの同等のものに置き換えることができることを意味する場合)。 、しかし、CPUアフィニティを設定する唯一の方法は、そのCPUが他のアプリケーションによって非常に負荷が高く、他のCPUがアイドル状態にある場合でも、プログラムがすべてのスレッドに対して特定の選択されたCPUを使用するように制限することです.
補遺
次のコードを検討してください。
私の理解では、メモリバリアがなくても、Intel プロセッサで実行されているコードは、書き込みが再配列されないことを保証します。したがって、スレッド 2 では、「Smiley」、「George」、または「Simpson」、「Bart」のいずれかが読み取られます。ただし、.net メモリ モデルはそれよりも弱く、スレッド 2 が不完全なオブジェクトを参照する可能性があるプロセッサ上で .net プログラムが実行されていることに気付く可能性があります ( への書き込みが へSharedPerson
の書き込みの前に発生する可能性があるためnewPerson.FirstName
)。にメモリ バリアを追加するMaybeMemoryBarrier1
と、その危険を回避できますが、実際に必要かどうかにかかわらず、メモリ バリアにはパフォーマンス コストがかかります。
最小要件の .net メモリ モデルは、スレッド 2 がそれ自体を読み取る前にMaybeMemoryBarrier2
によって参照されるオブジェクトに決してアクセスしないことが保証されている場合に必要なほど弱いとは思いません(上記のコードの場合のように、新しいインスタンスは、に格納される前に外部コードに公開されないため)。一方、状況が少し変わったので、レコードを作成し、それをキューに入れたとします(キュー自体に必要なすべてのロックとメモリ バリアがあると仮定します)。その後、プロセッサは次のことを行います。SharedPerson
SharedPerson
SharedPerson
Thread 2
JobInfo
Thread 1
スレッド 1 にメモリ バリアがあり、スレッド 2 にはない場合、スレッド 2 がJobInfo
作成したレコードが に表示されるのを確認したときにCurrentJob
、そのStartTime
フィールドを正しく読み取る (キャッシュされた値または部分的にキャッシュされた値が残っているのを確認しない) という保証はありますか?Thread 2
あの物体を操作していた時から?
c++ - std::mutex はフェンスを作成しますか?
遺言書をロックするstd::mutex
と、常にメモリ フェンスが取得されますか? それがあなたにフェンスを取得することを暗示しているのか、強制しているのかはわかりません.
アップデート:
RMF のコメントをフォローアップするこのリファレンスを見つけました。
arm - ARM ウィーク メモリ モデルによって保証される順序
弱いメモリ モデルと強いメモリ モデルの基本的な違いを理解しています。しかし、weak の正確な定義はなく、アーキテクチャ (ここでは ARM) に依存します。
ARM インフォセンターのドキュメントを確認しましたが、まだ多くのことが明確ではありません。誰かリストアップしてくれませんか -
ARM と PPC(Power PC) メモリ モデルの違いを説明できる人にはボーナス ポイントです。
c++ - C++ コンパイラは C++11 アトミックをサポートするが、C++11 メモリ モデルはサポートしない
Clang と g++ C++11 の実装状況を見ていると、奇妙なことに気付きました。
これらは C++11 アトミックをサポートしていますが、C++11 メモリ モデルをサポートしていません。
アトミックを使用するには C++11 メモリ モデルが必要であるという印象を受けました。それでは、アトミックとメモリ モデルのサポートの違いは何でしょうか?
メモリ モデルのサポートがないということは、std::atomic<T>
seq を使用する正当な C++11 プログラムが一貫していないことを意味しますか?
参照:
http://clang.llvm.org/cxx_status.html
http://gcc.gnu.org/gcc-4.7/cxx0x_status.html
linux - BSD または Linux でプログラムのデフォルトのスタック設定を制御するには?
実行中のプログラムがあり、BSDの/proc/[pid]/map (または Linux の/proc/[pid]/maps ) を見ると、次のような行が表示されます。
これがスタックです。私の PC-BSD プログラムはすべて、この同じスタック境界 0xbfc00000 を使用します。Linux では、ASLR をオフにすると、同様のことが起こります。
一部のプログラムでこれらの設定を試してみたいのですが、エルフ プログラム ヘッダーまたはセクション ヘッダーでスタックが指定されていないようです。
したがって、次のような設定を変更したい場合:
- スタックの実行権限を変更する
- スタック境界を別の値に設定する
個々のプログラムの「スタック設定」を変更する方法はありますか? システム全体はどうですか?
x86 - メモリの並べ替え: 以前のストアを使用して、別の包括的な場所にロードを並べ替えることができますか?
intel のプロセッサ マニュアル:セクション 8.2.3.4 のリンクでは、ロードは以前のストアを別の場所に並べ替えることができるが、以前のストアを同じ場所に並べ替えることができないと記載されています。
したがって、次の 2 つの操作を並べ替えることができることを理解しています。
また、次の 2 つの操作は順序を変更できません。
しかし、ストアとロードが別の場所にある場合、ロードはストアを完全に取り囲んでいます。たとえば、次のようになります。
では、この場合の 'y' は 0 にできますか?
編集(@Hans Passant) 状況をさらに説明するために、この手法を使用して、ロックされた命令を使用せずにスレッド間の一種の準同期を考案できるかどうかを確認しようとしています。
したがって、グローバル変数が与えられた場合のより具体的な質問は次のとおりです。
そして、次のコードを実行する 2 つのスレッド:
スレッド 1:
スレッド 2:
両方のスレッドで 'y' を 1 にすることはできますか?
注: __builtin_popcountl は、変数に設定されたビット数をカウントする組み込みの gcc 組み込み関数です。
java - 起こることを理解する方法-一貫する前に
JLSの第17章では、 「起こる-一貫性を保つ前に」という概念を紹介しています。
一連のアクションAが発生します-一貫する前に、Aのすべての読み取りrについて、W(r)がrから見た書き込みアクションである場合、hb(r、W(r))またはwv = rvおよびhb(W(r)、w)およびhb(w、r)"となるような書き込みwがAに存在します。
私の理解では、それは次の言葉に等しい:...、それは...でも...でもない場合です。
したがって、最初の2つの質問は次のとおりです。
- 私の理解は正しいですか?
- 「wv=rv」とはどういう意味ですか?
また、例を示します:17.4.5-1
最初の実行順序:
注文自体は、2つのスレッドが交互に実行されることをすでに示しているので、私の3番目の質問は次のとおりです。
私の理解では、r2とr1の両方の理由は、最初の書き込みが0であることがわかるのは、AとBの両方が揮発性フィールドではないためです。ですから、私の4番目の質問は、私の理解が正しいかどうかということです。
2番目の実行順序:
発生前の一貫性の定義によると、この実行順序が発生する前に発生することを理解することは難しくありません(私の最初の理解が正しければ)。したがって、私の5番目と6番目の質問は次のとおりです。現実の世界にこの状況(読み取りは後で発生する書き込みを参照)が存在しますか?もしそうなら、私に実際の例を教えていただけますか?
java - 正しく同期されたプログラムでもデータ競合は可能ですか?(パートI)
JLSから2つの結論があります。
- C1:プログラムにデータ競合がない場合、プログラムのすべての実行は逐次一貫性があるように見えます。
data-race-free => sequentially consistent
- C2:プログラムが正しく同期されている場合、プログラムのすべての実行は順次一貫しているように見えます。
correctly synchronized => sequentially consistent
C1の逆が真である場合、次のように結論付けることができます。
- C3:プログラムが正しく同期されている場合、データの競合は発生しません。
correctly synchronized => data-race-free
しかし、残念ながら、JLSにはそのようなステートメントがないため、4番目の結論に到達します。
- C4:プログラムは正しく同期され、データの競合が発生する可能性があります。
しかし、私はこのアプローチに満足しておらず、非公式な方法でもサンプル的な方法でも、この結論が正しい(または間違っている)という証拠を入手したいと思います。
まず、データ競合を含むマルチスレッドプログラムの逐次一貫性のある実行を示すコードセグメントは、この問題を理解して解決するのに役立つと思います。
真剣に検討した結果、まだ適切なサンプルが見つかりません。では、そのようなコードセグメントを教えていただけませんか。