web-dev-qa-db-ja.com

スレッドセーフなstd :: atomic <vector <int >>を作成できますか?

n=1000回実行する必要がある関数があります。この関数はモンテカルロスタイルのシミュレーションを行い、結果としてintを返します。 nthreads=4を並行して実行したい。スレッドが1サイクルを終了するたびに、結果をstd::vector<int>に入れます。したがって、1000サイクル後、統計によって調べることができる1000 intsのベクトルができました。

std::vectorはスレッドセーフではないので、std::mutexを検討しました(きっとうまくいきます)。

しかし、私はベクトルをアトミックであると宣言して、ミューテックスを回避できるかどうか疑問に思いますか? std::atomic<std::vector<int>>を持つことは可能ですか?また、Push_backなどを使用できますか?

19
dani

する必要はありません。複数のスレッドからja std::vectorにアクセスすることは、まったく問題ありません。

  • あなたはオブジェクトを読む
  • 異なるオブジェクトに書き込む

したがって、サイズn=1000のベクターを作成し、スレッド番号(1〜4)に応じて、0〜249、250〜499などの要素をスレッドに割り当てます。

したがって、各スレッドはn/nthreads要素を計算します。

9
UniversE

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またはサイズコンストラクターを使用して、事前に割り当てたり、必要なintsを事前に構築します。したがって、同時スレッドは、ベクター自体ではなく要素を操作する必要はありません。

異なるスレッドから同じ要素へのアクセスがない場合、競合状態はありません。

同じことは、簡単にコピーできるint k[1000]にも当てはまります。ただし、スレッドは配列/ベクトル/リスト自体を変更するのではなく、要素を変更するので、その必要はありません。

22
Pixelchemist

Atomicは、簡単にコピーできる型でインスタンス化できます。ベクトルはそのようなタイプではありません。

4
DawidPi