問題タブ [lockless]
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.
multithreading - スピンロックに対するロックフリープログラミングの利点は何ですか?
スピンロックに対するロックフリープログラミングの利点は何だろうと思いますか? スレッド (A と呼ばれる) で CAS メカニズムを使用してロックフリープログラミングを行う場合、他のスレッドが CAS の値を変更した場合、スレッドはまだ必要があると思います。再びループします。そして、スピンロックを使うのと同じだと思います!
私はこれについてとても混乱しています。ロックの競合が激しくない場合に CAS とスピンロックを使用するのが適していることはわかっていますが、どのシナリオでロックフリーを使用し、スピンロックを使用する必要があるか説明できますか?
c++ - 非アトミック サイズのアイテムを使用したロックレス デキュー
「弱いメモリ モデルの正確で効率的なワークスティーリング」で説明されているように、ワーカー両端キューを使用しています。キュー アイテムのサイズを 16 バイトにしたいのですが、Intel/AMD Windows x64 と VS 2019 だけに関心があります。
16 バイト (たとえば __m128) で整列されたロード/ストアは、最新のプロセッサでは通常アトミックであることを理解していますが、仕様では保証されていません。
両端キューのタイプは次のとおりです。
重要なことに、配列バッファー項目は特にアトミック型を持っています。これをVS2019でコンパイルすると、スピンロックでバッファアイテムのサイズが肥大化することがわかります-これは望ましくありません。それを防ぐことは可能ですか?具体的には、特定の保証が付いている x64 のみを気にします。
両端キューに対するアクションは、次の関数によって与えられます。
その多くは冗長であり、x64 で最適化する必要があります。実際、論文では、thread_fence(seq_cst) 行の take 関数でメモリ フェンスのみが必要であると指定されています。キュー アイテム タイプのサイズが 16 バイトの場合、これが正しいかどうかはわかりませんが?
take()/push() は同じスレッドで発生する必要があるように見えるため、それらの間に問題はありません。したがって、steal() を呼び出して部分的に書き込まれた 16 バイト項目を読み取るスレッドは危険です。しかし、push() は 16 バイトすべてが書き込まれた後にのみメモリ フェンスを実行し、その後のみ下部を更新するため、x64 ではこれは問題ではないようです。
バッファー項目のアトミック修飾子を削除し、揮発性ポインターを介してバッファーとの間でプレーンな割り当てを使用する実験を行いました。そして、それはうまくいくように見えましたが、明らかにそれは確実ではありません!
これが不可能な場合、おそらく cmpxchg16b を使用することは、私の特定のケースで 16 バイトをロード/保存するためのより良いオプションでしょうか? または、キュー アイテムをインデックスとして使用し、インデックス付きの 16 バイト スロットをロックなしで割り当てることによって、すべてが複雑になります。
したがって、私の質問の簡略版は次のとおりです。x64では、配列バッファータイプの定義を、アトミック修飾されていない16バイト構造体アイテムの配列への揮発性ポインターに変更し、上記の関数でそれらのアイテムのロードとストアを変更できますか?単純な非アトミック代入式に?