n=1000
回実行する必要がある関数があります。この関数はモンテカルロスタイルのシミュレーションを行い、結果としてint
を返します。 nthreads=4
を並行して実行したい。スレッドが1サイクルを終了するたびに、結果をstd::vector<int>
に入れます。したがって、1000サイクル後、統計によって調べることができる1000 int
sのベクトルができました。
std::vector
はスレッドセーフではないので、std::mutex
を検討しました(きっとうまくいきます)。
しかし、私はベクトルをアトミックであると宣言して、ミューテックスを回避できるかどうか疑問に思いますか? std::atomic<std::vector<int>>
を持つことは可能ですか?また、Push_back
などを使用できますか?
する必要はありません。複数のスレッドからja std::vector
にアクセスすることは、まったく問題ありません。
したがって、サイズn=1000
のベクターを作成し、スレッド番号(1〜4)に応じて、0〜249、250〜499などの要素をスレッドに割り当てます。
したがって、各スレッドはn/nthreads
要素を計算します。
C++ 11§29.5/ 1は言う
汎用的なクラステンプレートアトミックがあります。テンプレート引数Tの型は、簡単にコピー可能でなければなりません(3.9)。
自明にコピー可能とはどういう意味ですか?
§3.9は言う
スカラー型、自明にコピー可能なクラス型(9節)、そのような型の配列、およびこれらの型のcv修飾バージョン(3.9.3)は、総称的に自明にコピー可能な型と呼ばれます。
クラス型の場合(std::vector
が含まれる):
自明にコピー可能なクラスは、次のようなクラスです。
- 重要なコピーコンストラクターがありません
- 重要な移動コンストラクタはありません
- 重要なコピー代入演算子はありません
- 重要な移動代入演算子はありません
- ささいなデストラクタを持っています
このリストによると、std::vector
は簡単にはコピーできないため、std::atomic<std::vector<int>>
は使用できません。
事前にサイズがわかっているため、ベクトルを別の場所に再割り当てする必要があるメソッドを使用する必要がないため(Push_back)
など)。std::vector<int>::resize
またはサイズコンストラクターを使用して、事前に割り当てたり、必要なint
sを事前に構築します。したがって、同時スレッドは、ベクター自体ではなく要素を操作する必要はありません。
異なるスレッドから同じ要素へのアクセスがない場合、競合状態はありません。
同じことは、簡単にコピーできるint k[1000]
にも当てはまります。ただし、スレッドは配列/ベクトル/リスト自体を変更するのではなく、要素を変更するので、その必要はありません。
Atomicは、簡単にコピーできる型でインスタンス化できます。ベクトルはそのようなタイプではありません。