問題タブ [false-sharing]
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を使用していますが、ここに関数があります:
機能はその通りです。std::vector
スレッドのすべての結果を格納するがあることがわかります。
私の質問は:std::vector
偽の共有を引き起こす可能性がありますか? std::vector
可能であれば、スレッドの結果を保存するために使用しているときに誤った共有を回避する方法はありますか?
c++ - ウィンドウでのマルチスレッド フォールス シェアリング
こんにちは、私のテスト コードから予想される偽の共有が発生しないという問題が発生しています。
複数のスレッドを均一に管理するプロセス固有のスレッド マネージャーを作成しようとしています。
独自のスレッド マネージャ クラスはスレッド プールではなく、指定されたスレッドにタスク関数を割り当てて動作し、タスク関数の戻り値を取得することができます。また、スレッドマネージャはタスクのサイズ(計算量)を気にしません。
スレッド マネージャは、スレッド (メイン スレッド) によって計算部分を処理するために使用され、非常に頻繁に使用されます。この理由は、私のプロセスにはゲーム ループ デザイン パターンがあり、ゲーム ループを 120 FPS 以上にしたいためです。つまり、1 つのゲーム ループを 8.3 ミリ秒未満で実行する必要があります。スレッド (メイン スレッド) は、1 つのゲーム ループ内でこのタスクの割り当てを何度も行う可能性があるため、コンテキスト切り替えのコストを削減/排除することが私の主な関心事でした。私の結論は、スレッドマネージャーのスレッドをスピンロックさせることでした。
つまり、ゲーム ループは、次の 2 つの手順を何度も繰り返します。
- メイン ループはタスクをスレッド マネージャーに割り当てます。
- スレッド マネージャによるタスクの結果を待ちます。
以下は私のテストコードです。
ThreadManager.h
main.cpp
インターロック系の関数、__forceinline、静的変数のダーティー宣言など、本当に申し訳ありません。
一方、ロック変数に「long long」を使用した理由は、「bool」型がなかったからです。「短い」で試してみたかったのですが、「短い」と「長い・長い」の時間を測ってみると、あまり差がありませんでした。むしろ、「ショート」の方が少し遅く、その理由は 64 ビット環境で 16 ビット レジスタを使用しているためだと思います。また、bool 型または short 型は、メモリ アラインメントの問題を引き起こす可能性があります。そこで「ロングロング」タイプを使用。
CThreadManager がプライベート コンストラクターを持つ理由は、"new CThreadManager()" を明示的に禁止するためです。
「reinterpret_cast」の使用は最小限に抑えられます。コストはコンパイル時間だと思っていましたが、スタックオーバーフローからランタイムコストがあるという質問を見ました。まだよくわかりません。そのため、スレッド関数が開始されたときに一度だけ使用してください。
これまでのところ、変更して偽共有現象を確認しました
SData::ullData[8] -> SData::ullData 1
また、Sleep(0) を使用すると、WaitForResult() でのスレッド タイム スライスの無駄が大幅に削減され、スレッド内の合計実行時間も削減されました。
このコードの結果は
私の環境では。
しかし、SData::ullData 以外にも、s_pThreadQuits、s_pTaskLocks、s_ppTasks、s_pTaskResults など、偽の共有が必要な場所があることに気付きました。
これらの変数で偽共有が発生しないのはなぜですか?
[編集]
「偽の共有」とは、「異なるスレッドによってアクセスされるメモリアドレスが同じキャッシュラインを共有する」ということです。
- SData g_stDataN (各 FunctionN() 内)
- s_pThreadQuits、s_pTaskLocks、s_pTaskResults、s_ppTasks (Thread() 内)
2.変数もg_stDataN(私の環境では64バイト)と同じようにキャッシュにロードされます。「パディング」メソッドの結果を達成して偽共有を回避するために、SData のサイズを 64 バイトに設定しました。
ただし、s_pThreadQuits のサイズが 64 バイトに設定されておらず、パディングもされていない限り、フォールス シェアリングも必要です。
下のこの画像のように。
画像のソースは https://www.codeproject.com/Articles/85356/Avoiding-and-Identifying-False-Sharing-Among-Threaからのものです