2016-02-08 4 views
8

Iは、複数のスレッドからfloat Sを計算し、次のように同じvector<float>の非重複範囲内に結果を格納しています:同じベクターの異なる範囲に対して複数のスレッドからstd :: copyを呼び出すことは安全ですか?

を私はそれがvector::reserveを使用して事前に割り当てられたスレッドのいずれかを実行する前に。各スレッドで

スレッド固有の結果の vectorを計算し、このようなターゲットコンテナにコピーされます。

vector<float>::iterator destination = globalVector.begin() + threadSpecificIndex; 
std::copy(localVector.begin(), localVector.end(), destination); 

これは安全な練習ですか?ベクトルは大きさを固定している(と、それはあなたの質問から持っているようにそれはそう)、および範囲は、その後、重複していない場合

+8

'std :: vector :: reserve'は実行しません。実際には' resize() 'する必要があります。そうしないと、ベクトルの実際の' end() 'を超えて書き込みます。 – mindriot

+0

@mindriotコメントに追加するには:格納している型にデフォルトのコンストラクタがない場合は、直接型の代わりに 'boost :: optional'のようなものを使うことができます。これは、自分自身を完全に構築していない「まだ実際ではない」オブジェクトの1つを作成せずに何かが失敗したかどうかを知ることができるという利点をもたらしました。それらは嫌悪感です。 –

答えて

7

最初のvector::reserveは実際には要素を作成しません。ベクトルの容量を設定するだけです。要素が必要な場合は、vector::resizeが必要です。または、必要なサイズのベクトルを構築するだけです。

第2に、スレッド間に共有オブジェクトがあり、そのうちの少なくとも1つが同期が必要なライターである場合です。この場合、 "オブジェクト"は反復子の範囲であり、重複しないので、この点に関しては大丈夫です。ベクトルのサイズが変更されない限り、あなたは大丈夫です。

あなたがこれで持つことができる1つの問題は、誤った共有です。同じキャッシュラインに異なるスレッドが使用している変数が含まれている場合、そのラインの変数が更新されるたびにそれらのキャッシュラインを再同期させる必要があります。これは、コードのパフォーマンスをかなり低下させる可能性があります。

+0

キャッシュについての良い点。他のコンテナがここでうまく収まるかどうかは疑問ですが、このキャッシュのものであっても、ベクトルが最も高速です。 –

+0

@piotrsmaronベクトルが通常はより良いオプションです。イテレータの範囲がキャッシュラインより大きい限り、誤った共有は問題ではありません。私は潜在的な落とし穴としてそれを言いました、そして私は小さな範囲でそれを見ました。 – NathanOliver

+0

@jaggedSpire問題ありません。文法のレビューをありがとう。 – NathanOliver

2

  1. ベクトルが
  2. 異なるスレッドを再割り当てされることはありませんしません同じメモリにアクセスする

このように私はここにデータレースは見ません。 (しかし、あなたの質問に対する第1のコメントによれば、そのベクトルは使用時にこの固定サイズを持つようにする必要があります)。 std :: copyの "Data Races"セクションも参照できます。コピー:http://www.cplusplus.com/reference/algorithm/copy/

+0

「ベクトル」 –

+0

の場合を除き、そうです。ベクトルによって、私はベクトルを意味しました。質問の著者はこれについて尋ねていましたが、これを修正することに感謝します。 –

関連する問題