問題タブ [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.
concurrency - メモリバリアはSMPでのみ意味がありますか?
メモリバリアが必要な理由は理解できますが、ユニプロセッサの場合はわかりません。
UPを使用してもバリアに対処する必要がありますか?すべてのドキュメントはSMPでそれらを説明していますが、UPでは説明していません。
r2 == 0
次のコードでは、ポイントaにある可能性はありますか?
.net - MemoryBarriers と Parallel Extensions
Parallel Extensions を使用する場合、MemoryBarriers について考慮する必要はありますか?
編集 - 元の質問が自由回答形式だったので詳しく説明します: (@xanatos の回答は私が探していたものでした)
具体的な例を挙げると、Parallel.ForEach を使用し、各反復がクラス内のプロパティの値を設定するとします (各反復は独自の特定のプロパティを設定し、2 つの反復で同じプロパティの値を設定することはありません)。Parallel.ForEach を呼び出した同じスレッドで、Parallel.ForEach から設定されたプロパティにアクセスします。
c# - 同時インターロックと読み取りにはメモリバリアまたはロックが必要ですか?
これは単純な問題ですが、なぜメモリバリアが必要なのかを読んだ後、私はそれについて非常に混乱しています。
以下の例では、さまざまなスレッドが Increment と Counter を繰り返し呼び出していると想定しています。
誤解していたらごめんなさいなぜメモリバリアが必要なのですか? しかし、_counter の値を読み取るときに、上記のクラスが鮮度を保証していない可能性があることを示唆しているようです。Counter プロパティに繰り返しアクセスしているスレッドは、Counter の古い値で永遠に動かなくなる可能性があります (レジスタにキャッシュされているため)。
必要になる前にメモリバリアまたはロックはreturn _counter;
ありますか?
java - メモリバリアの良い紹介はありますか?
メモリバリアとJavaコードの通常の落とし穴に関する優れたオンライン紹介を探しています。
- 使用
synchronized
頻度が高すぎる、または使用頻度が不十分 - 使用するタイミング
volatile
とfinal
- ダブルチェックロック
- 等
一般的な問題 (複数のスレッドがアクセスできるマップの作成や、値が遅延して追加される場所など) を解決する方法の動作や例を示すコードに特に興味があります。
c - 関数呼び出しは、最新のプラットフォームにとって効果的なメモリバリアですか?
私がレビューしたコードベースで、次のイディオムを見つけました。
「保持してください」と、私のチームのシニアメンバーである作者に言いました。「ここにはメモリバリアはありませんglobal.data
。キャッシュからメインメモリにフラッシュされる保証はありません。スレッドAとスレッドBが実行される場合2つの異なるプロセッサ-このスキームは失敗する可能性があります。」
シニアプログラマーはニヤリと笑い、靴ひもを結ぶ方法を5歳の男の子に説明するかのようにゆっくりと説明しました。彼の長いあごひげを引っ掻くために一時停止しました、「しかし、私たちはこのイディオムにバグがあったことはありません」。
「しかし、それは本の中で述べています...」
「静かに!」と彼はすぐに私を黙らせました。「理論的には保証されないかもしれませんが、実際には、関数呼び出しを使用したという事実は事実上メモリバリアです。コンパイラは命令global.data = data
を並べ替えません。関数呼び出しでそれを使用する人は誰でも、x86アーキテクチャは、スレッドBがパイプからコマンドを読み取るまでに、他のCPUがこのグローバルデータを確実に認識できるようにします。実際の問題は十分にありますので、ご安心ください。偽の理論上の問題に余分な労力を費やす必要はありません。
「私の少年は安心してください。やがて、本当の問題を博士号を取得する必要のある非問題から分離することが理解できるでしょう。」
彼は正しいですか?それは実際には問題ではありませんか(x86、x64、ARMなど)?
それは私が学んだすべてに反します、しかし彼は長いあごひげと本当にスマートな外見を持っています!
彼が間違っていることを証明するコードを見せてくれれば、追加のポイントがあります!
multithreading - _ReadWriteBarrierは、スレッド間で動的に割り当てられたバッファーの可視性を保証しますか?
VisualC++とWindows7およびXPを使用しています。プログラムに2つのスレッドがあり、両方が作成された後、1つのスレッドが動的にバッファーを作成し、そのアドレスをグローバルポインターに割り当ててから、そのバッファーにデータを書き込みます。_ReadWriteBarrierを呼び出すと、2番目のスレッドに対するそのデータの可視性が保証されますか?
例えば:
グローバル変数と同様に、のアドレスの可視性を保証するドキュメントから私は信じています。しかし、それはまた、で作成されたバッファ自体の可視性を保証しますか?それも必要ですか?_ReadWriteBarrier
buff
buff
main
c# - 構造体配列のc#並行性
構造体の配列が与えられた場合:
そして、単一の要素が最大で2つのスレッドによって同時に書き込まれる可能性があることに基づいてそれらの要素に書き込みを行うスレッドタスクプール(各ダブルフィールドに1つずつ)(トピックごとに効果的にアップストリームキューイングがあります)。
そして、doubleは64ビットでアトミックに記述できるという知識。(これを編集して、元々32ビットと誤って言った)
配列内のすべての値を使用して定期的に計算を実行する必要があり、計算中にそれらの値が一貫していることを望みます。
したがって、次の方法でアレイのスナップショットを作成できます。
今私が持っている質問は、同期の詳細に関するものです。メンバーを揮発性にした場合、読み取り/書き込みの取得/リリースはアレイレベルではないため、クローンの作成にはまったく役立たないと思います。
これで配列ロックを設定できましたが、これにより、配列にデータを書き込む最も頻繁なプロセスで多くの競合が発生します。だから理想的ではありません。
または、行ごとのロックを設定することもできますが、クローンを作成する前にすべてを取得する必要があるため、これは非常に面倒です。その間、書き込みはすべてバックアップされます。
スナップショットの値がマイクロ秒などの場合、最新の値でなくても問題はないので、ロックがなくても問題は解決できると思います。私の唯一の懸念は、持続的な期間のキャッシュの書き戻しがないシナリオが存在する可能性があるかどうかです。これは私が心配すべきことですか?ライターはTPLデータフローにあり、唯一のロジックは構造体に2つのフィールドを設定することです。ただし、関数スコープがキャッシュのライトバックと相関する傾向があるかどうかはわかりません。
考え/アドバイス?
編集:構造体の変数へのインターロック書き込みを使用した場合はどうなりますか?
edit2:書き込みの量は読み取りよりもはるかに多いです。Nos&Lastフィールドに書き込む2つの別個の同時サービスもあります。したがって、それらは同時に書き込まれる可能性があります。これにより、アトミック性の参照オブジェクトアプローチで問題が発生します。
edit3:詳細。配列が30〜1000の要素であり、各要素が1秒間に複数回更新される可能性があると想定します。
.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# - システム稼働時間とメモリバリア
システムの稼働時間を確保するための堅牢な方法が必要で、最終的に次のようなものを使用しました。人々がそれを読むのを助けるためにいくつかのコメントを追加しました。これは.NET 3.5アプリケーションで実行する必要があるため、タスクを使用できません。
私が苦労している部分は、どこThread.MemoryBarrier()
に配置すればよいですか?値を読み取る前に配置していますが、現在のスレッドまたは別のスレッドが値を書き込んだ可能性があります。上記は正しいように見えますか?
編集、ダニエルに基づく回答
これが私が最終的に実装したものです。両方の洞察に感謝します。
編集 2
Bob のコメントに基づいて更新されました。
c++ - std::mutex はフェンスを作成しますか?
遺言書をロックするstd::mutex
と、常にメモリ フェンスが取得されますか? それがあなたにフェンスを取得することを暗示しているのか、強制しているのかはわかりません.
アップデート:
RMF のコメントをフォローアップするこのリファレンスを見つけました。