問題タブ [stdatomic]
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++ - 移動専用タイプをクラスに追加すると、そのクラスは移動専用タイプになりますか?
Scott Meyers の「Effective Modern C++」で、彼は次のように書いています。
は移動のみの型 (つまり、移動はできるがコピーはできない型) であるため、 に追加すると
std::mutex
、コピーできなくなるという副作用があります。ただし、移動は可能です。m
Polynomial
Polynomial
std::mutex m
ここで、クラスの const メンバー変数へのアクセスを保護する必要がある理由を説明するコンテキストで、クラスにメンバー変数として aを追加しPolynomial
ます (マルチスレッド中)。私は彼が説明した概念を理解しました。std::mutex
しかし、もう少し説明する必要があるのは、「クラスに移動のみのタイプを追加すると、そのクラスが移動のみのタイプとしてコピー不可になるのはなぜですか」ということstd::atomic
です。クラスに移動のみの型の変数を追加してもコピー操作を実行したい場合、どうすればそれを乗り越えることができますか?
multithreading - リーダースレッドとライタースレッドが 1 つずつある場合、std::atomic_ を使用する必要がありますか?
リーダー/ライターのシナリオで std::shared_ptr を使用しようとしています。1 つのスレッドが常に新しい情報を受け取り、最新のデータへのスマート ポインターを保持します。遅い計算を実行するときが来たら、すべてのデータへのスマート ポインターを取得して、一貫性のあるデータを表示していることを確認します。以下の例では、a と b を使用すると、それらが一緒に属していることがわかります。
ここでatomic_loadとatomic_storeを使用する必要があるかどうかわかりませんか? 一貫性があり有効である限り、どのバージョンの Foo を見ているかはあまり気にしません。
では、このコードを 2 つの異なるスレッドから動作させるには、スマート ポインターでアトミックを使用する必要がありますか?
ありがとう、
ポール
c++ - メモリ フェンス: 取得/ロードおよび解放/格納
std::memory_order_acquire
との私の理解は次のstd::memory_order_release
とおりです。
取得とは、取得フェンスの後に出現するメモリ アクセスをフェンスの前に並べ替えることができないことを意味します。
リリースとは、リリース フェンスの前に出現するメモリ アクセスをフェンスの後に並べ替えることができないことを意味します。
私が理解できないのは、特に C++11 アトミック ライブラリでは、取得フェンスがロード操作に関連付けられ、リリース フェンスがストア操作に関連付けられている理由です。
明確にするために、C++11<atomic>
ライブラリでは、メモリ フェンスを次の 2 つの方法で指定できます。
または、次std::memory_order_relaxed
のようにフェンスを個別に使用して指定することもできます。
私が理解していないのは、上記の acquire と release の定義を考えると、なぜ C++11 がacquireをloadに、releaseをstoreに関連付けるのかということです。はい、取得/ロードとリリース/ストアを使用してスレッド間で同期する方法を示す多くの例を見てきましたが、一般的には、取得フェンス (ステートメントの後のメモリの並べ替えを防ぐ) とリリースのアイデアのようです。フェンス (ステートメントの前にメモリの並べ替えを防止する) は、ロードとストアの考え方と直交しています。
では、たとえば、コンパイラが次のように言わないのはなぜですか。
memory_order_relaxed
を使用してから別のステートメントを使用することで上記を達成できるatomic_thread_fence(memory_order_acquire)
ことはわかっていますが、もう一度、ストアを直接使用できないのはなぜmemory_order_acquire
ですか?
これの考えられるユースケースは、他のスレッドに影響を与える可能性のある他のステートメントが実行される前にx = 10
、ストア、たとえばが発生するようにしたい場合です。
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++ - std::アトミックメインスレッドで変更されたが、他のスレッドでは変更されていない
std::atomic を使用して、チェス AI の一部のスレッドを協調的に停止しようとしています。StopPondering() を呼び出したときにスレッドが実行され続ける理由がわかりません。StopPondering で中断すると、Searching が正しく設定されていることがわかりますが、2 つのスレッドのいずれかで中断しても、その値は true のままです。Windows 8.1 で VS 2013 を使用しています。関連するコードのサブセットを以下に示します。
AI0.h
AI0.cpp
大文字と小文字が一致しないことをお詫びします。
- - - - -編集 - - - - -
問題が解決しました。私は愚かにも AI0 の複数のインスタンスを作成していました。一部の人が実際に疑ったように、スレッドを生成したのと同じインスタンスで StopPondering() を呼び出していませんでした。これは明らかにメモリ リークでした。現在、AI0 シングルトンは 1 つしかなく、すべてが期待どおりに機能しています。失敗してごめんなさい。
c++ - リラックスした順序でのアトミック値の変更
次のコード スニペットがあるとします。
0 0
問題は、結果として得られるかどうかです。
ここでは、両方のスレッドがリラックスしたメモリ順序で読み取りと変更a
を行っているため、両方のスレッドが のゼロ値を認識しているように見えますa
。しかし、実際には0 1
またはしか見えません1 0
。