問題タブ [seqlock]
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 アトミック ライブラリを使用して seqlock ロックを実装する方法
C++11 アトミック ライブラリを使用して seqlock を作成したいと考えています。stackoverflow の seqlock に関するいくつかの質問を読みましたが、誰も助けてくれませんでした。私が使用するアルゴリズムは一般的で、どこにでもあります。それが私のコードです。
B と C で memory_order タグを正しく使用していることを確認します。
AとDでは正しくないと思います。
保護されたデータの読み取りと書き込みを同時に行うことを考えてみてください。D のフラグの読み取り値が古すぎて、write_lock() によって書き込まれた最新の値を読み取っていないのではないかと心配しています。しかし、保護されたデータの最新の値を読み取ります。書き込みスレッドによって書き込まれます (x86 システムでは発生しない可能性がありますが、コードが x86 で実行されているとは想定していません)。読み取りスレッドが保護されたデータの読み取りを終了した後、フラグの読み取り値が古すぎるため、シーケンスが増加したことがわかりません。読み取りスレッドがループから抜け出し、バグが発生します。
(1)で保護されたデータの読み取り値は(4)で書き込まれ、(2)で読み取られたフラグの値は(3)で書き込まれません(前回書き込みロックを解除したときに書き込まれます)。バグがあると思う理由。
しかし、これを修正する方法が本当にわかりません。read_leavee() と write_locke() の間に「同期」関係を作ろうとしました (「read_leave() を write_locke() と同期させたい」)。しかし、ストアはありません。アクションは read_leave() で、失敗しました。
(ああ、C++ の標準仕様は難しすぎて理解できません。私が英語圏ではないことも一因です。)
c++ - `memory_order_seq_cst` を使用して、ロード全体で GCC の並べ替えを行います。これは許されますか?
基本的なseqlockの単純化されたバージョンを使用して 、gcc はload(memory_order_seq_cst)
でコードをコンパイルするときに、非アトミック ロードをアトミックに並べ替えます-O3
。この並べ替えは、他の最適化レベルでコンパイルする場合や、clang でコンパイルする場合 ( on であってもO3
) は観察されません。この並べ替えは、確立する必要がある同期との関係に違反しているようです.gccがこの特定のロードを並べ替える理由と、これが標準で許可されているかどうかを知りたいです.
次のload
関数を検討してください。
seq_
seqlock 手順に従って、このリーダーは、 であると定義されているの 2 つのインスタンスをロードできるようになるまでスピンしますstd::atomic<std::size_t>
。value
の 2 つの負荷の間seq_
)。さらに、これらのロードは (デフォルトの引数として) でタグ付けされているため、最初のロードを超えて上に並べ替えたり、後者の下に並べ替えたりすることはできないためmemory_order_seq_cst
、命令は反復ごとに実行されると思います。copy = value;
ただし、生成されたアセンブリvalue
は、最初のロードの前からロードを発行しseq_
、ループの外でも実行されます。value
これにより、不適切な同期や、seqlock アルゴリズムによって解決されない破損した読み取りが発生する可能性があります。sizeof(value)
さらに、これは が 123 バイト未満の場合にのみ発生することに気付きました 。何らかのタイプ >= 123 バイトになるように変更value
すると、正しいアセンブリが生成され、 の 2 つのロードの間の各ループ反復でロードされますseq_
。この一見恣意的なしきい値が、生成されるアセンブリを決定する理由はありますか?
このテスト ハーネス は、私の Xeon E3-1505M での動作を明らかにします。リーダーから "Observed: 2" が出力され、値 65535 が返されます。の観察された値seq_
と から返された負荷のこの組み合わせは、 でパブリッシュするライター スレッドとで読み取るリーダー スレッドvalue
によって確立されるべき同期-関係に違反しているようです。seq.store(2)
memory_order_release
seq_
memory_order_seq_cst
sizeof(value)
gcc がロードを並べ替えるのは有効ですか? もしそうなら、 123 未満の場合にのみそうするのはなぜですか? 最適化レベルに関係sizeof(value)
なく、ロードの順序を変更しません。Clang の codegen は適切で正しいアプローチだと思います。
c - Linuxカーネルでrwlockがseqlockよりも人気があるのはなぜですか?
Robert Love の LKD を読んだ後、rwlock と seqlock を学びました。どちらもスピンロックに基づいています。
リーダーとライターを区別すると、rwlock が spinlock よりも優れているため、パフォーマンスが向上します。ただし、rwlock を使用すると、ライターが空腹になります。
seqlock は rwlock がライタ ハングリーの問題を引き起こしている問題を解決しますが、rwlock よりも seqlock の使用が少なくなります。では、なぜ rwlock が seqlock よりも人気があるのでしょうか?