1

2D配列とこの関数があるとしましょう:

void addVec(std::vector<std::vector<short> >& arr, size_t idx){ 
   arr[idx].push_back(idx);
}

std::vector<std::vector<short> > arr(2);
boost::threads th1(addVec, boost::ref(arr), 0);
boost::threads th2(addVec, booost::ref(arr), 1);
th1.join();
th2.join();

今では arr[0][0] = 0; になっているはずです。そして arr[1][0] = 1; 問題は、これが安全かどうかです。内部的には、スレッドはベクトル メモリのさまざまな部分に値を追加する必要があります。サイズ 2 の先頭で構築されるため、内部ベクトルのみがサイズ変更され、スレッドの排他的アクセスが可能になります。

4

4 に答える 4

4

進んでいる道を進む前に、一歩下がって、自分の目標が何であるかを検討することをお勧めします。

まず、なぜコードを並列化したいのですか? プログラムをより速く実行したいと思っていると思います。つまり

  1. 動作するシーケンシャルな実装を書くことから始めるべきです。
  2. その実装をプロファイリングして調整する必要があります。
  3. プログラムがまだ目的に対して遅すぎる場合 (およびその場合のみ) は、次の場合に並列化する必要があります。
    1. プログラムの大部分は並列化できます (アムダールの法則を確認してください)。
    2. あなたのシーケンシャルな実装はキャッシュをうまく利用しています。シーケンシャル コードでもキャッシュがボトルネックになる可能性が非常に高いため、コードがキャッシュ効率的でない場合は、並列化するとおそらく遅くなります。

ポイント 1. と 2. は、おそらく時間を割くべきところです。おそらく、高度に調整されたシーケンシャルな実装は、ニーズに十分に対応でき、開発と保守がはるかに安価/簡単/高速になる可能性があります。

コードを並列化することに決めた場合は、OpenMPを検討する必要があります。スレッドは、人類が知っている並列プログラムを作成する最悪の方法の 1 つです。OpenMP のランタイム システムは遅すぎると思うかもしれませんが、一歩下がってその理由を考えてみてください。

アルゴリズムが多くのロックとバリアを必要とする場合は、より高速なロックとバリアを使用することで、わずかな速度向上を得ることができます。アルゴリズムを改善して、使用するロックとバリアの数を減らすと、大幅な高速化を実現できます。

于 2012-11-06T12:00:31.777 に答える
4

各スレッドは個別のベクトルにアクセスするため、これは安全なはずです。ただし、サイズ変更の原因となる可能性のあることを行うarrと、すべての賭けが無効になります...

于 2012-11-06T11:01:05.300 に答える
2

これは安全ですが、設計の観点からは、各スレッドに内部ベクトルのみを与える方が安全であるため、将来の安全でない動作の可能性は低くなります。

于 2012-11-06T11:00:02.193 に答える
2

はい、共有データを変更しないため、ユースケースでは安全です。ただし、std::vector<short>使用法を簡素化するために、への参照を各スレッドに渡すことをお勧めします。

void addVec(std::vector<short> & arr)
{ 
   arr.push_back(some_data);
}

std::vector<std::vector<short> > arr(2);
boost::threads th1(addVec, boost::ref(arr[0]));
boost::threads th2(addVec, booost::ref(arr[1]));
th1.join();
th2.join();
于 2012-11-06T11:00:15.377 に答える