2017-08-01 4 views
2

(非常に)大きなベクトルをとり、その中のすべての値を多次元(2D)ベクトルに再割り当てしようとしています。多次元ベクトルの子要素内の要素にスレッドセーフで書き込むことはできますか?

多次元ベクトルは、再配置を避けるために、値の集計に先立って両方のディメンションが正しいサイズにサイズ変更されています。

現在、私はそれをシングルスレッド化していますが、繰り返し発生する必要があり、大きなサイズ(〜7秒)のために非常に遅いです。問題は、例えば2D要素ごとのスレッドなど、スレッドセーフであるかどうかです。

いくつかの擬似コード:

vector<string> source{/*assume that it is populated by 8,000,000 strings 
of varying length*/}; 
vector<vector<string>> destination; 

destination.resize(8); 
for(loop=0;loop<8;loop++)destination[loop].resize(1000000); 

//current style 
for(loop=0;loop<source.size();loop++)destination[loop/1000000][loop%1000000]=source[loop]; 

//desired style 
void Populate(int index){ 
    for(loop=0;loop<destination[index].size();loop++)destination[index][loop]=source[index*1000000+loop]; 
} 

for(loop=0;loop<8;loop++)boost::thread populator(populate,loop); 

彼らは第二次元の要素を分離するために書いているので、私は、ネジ付きバージョンが動作する必要があることをを思うだろう。しかし、私は文字列を書くことがサイズ変更されているので、物事を壊すかどうかはわかりません。

答えて

1

スレッドセーフのみを考慮する場合、これは問題ありません。

Writing concurrently to distinct objects is allowed。 C++では、構造体の隣のフィールドや同じ配列内の要素であっても、オブジェクトは区別されます。オブジェクトのデータ型はここでは重要ではありませんので、stringの場合はintの場合と同様です。唯一重要なことは、あなたが操作する範囲が本当に完全に別個であることを保証しなければならないということです。オーバーラップがある場合は、データレースを手にしています。

ただし、ここで考慮する必要があるのはパフォーマンスです。これは非常にプラットフォームに依存しているので、言語標準はあなたにここで規則を与えませんが、いくつかの注意が必要です。たとえば、配列内の隣接要素が同じキャッシュ行に存在する可能性があります。したがって、ハードウェアが言語のスレッドセーフティ保証を実現できるようにするには、そのような要素へのアクセスを同期させる必要があります。例えば、あるスレッドが偶数インデックスを持つすべての要素を処理する方法で配列アクセスを分割し、奇数インデックスで動作するスレッドは技術的にスレッドセーフですが、両方のスレッドが競合する可能性があるためハードウェアに多くのストレスをかけます同じキャッシュライン上に記憶されたデータのために使用される。

同様に、あなたの場合、メモリバスに競合があります。スレッドがメモリに書き込むよりもはるかに速くデータの計算を完了できる場合は、スレッドがすべて最終的にメモリを待つため、実際には複数のスレッドを使用して何も取得できない場合があります。

並列処理が実際に問題の正しい解決策であるかどうかを判断する際には、これらのことを念頭に置いてください。

+0

コメントありがとうございました。ありがとうございました。すべてのコメントと、いくつかの注目を集めてくれました。 私の場合、各スレッドは2Dベクトルの全体の分岐を取得するので、範囲の衝突についての心配はありませんが、他の場合について知っておくとよいでしょう。 メモリとキャッシュの問題については、自分の状況で効率を判断するためにテストする必要があります。しかし、マルチスレッド化は必ずしも魅力的なことではないことを指摘することは良いことです。 –

関連する問題