マルチスレッド:ベクターにデータを入力している間に、ベクター内のデータを処理するにはどうすればよいでしょうか?

StackOverflow https://stackoverflow.com/questions/3681823

質問

シングルスレッドの Linux アプリを並列化したいと考えています。データ ファイルを読み取り、オブジェクトを作成し、それらをベクターに配置します。次に、各オブジェクトに対して計算負荷の高いメソッド (0.5 秒以上) を呼び出します。オブジェクトの作成と並行してメソッドを呼び出したい。qt と tbb を検討しましたが、他の選択肢も受け入れます。

ベクターが空の間にスレッドを開始するつもりでした。それぞれが電話するだろう makeSolids (下記) これには、interpDone==true になり、ベクター内のすべてのオブジェクトが処理されるまで実行される while ループがあります。ただし、私はスレッド化に関してはまったくの素人で、既製のソリューションを探していました。

QtConcurrent::map(Iter begin,Iter end,function()) とても簡単そうに見えますが、サイズが変化するベクトルには使用できませんね。そして、さらにデータを待つようにどのように指示すればよいでしょうか?

Intel の tbb も調べましたが、使用するとメインスレッドが停止してしまうようでした。 parallel_for または parallel_while. 。メモリマネージャーが推奨されているので、これは臭いです (オープンカスケードの mmgt はマルチスレッド時のパフォーマンスが低下します)。

/**intended to be called by a thread
\param start the first item to get from the vector
\param skip how many to skip over (4 for 4 threads)
*/
void g2m::makeSolids(uint start, uint incr) {
  uint curr = start;
  while ((!interpDone) || (lineVector.size() > curr)) {
    if (lineVector.size() > curr) {
      if (lineVector[curr]->isMotion()) {
        ((canonMotion*)lineVector[curr])->setSolidMode(SWEPT);
        ((canonMotion*)lineVector[curr])->computeSolid();
      }
      lineVector[curr]->setDispMode(BEST);
      lineVector[curr]->display();

      curr += incr;
    } else {
      uio::sleep(); //wait a little bit for interp
    }
  }
}

編集:要約すると、メインスレッドがベクターを設定すると同時にベクターを処理する最も簡単な方法は何でしょうか?

役に立ちましたか?

解決

この問題について深く考えていて、思っている以上のことが考えられているのか、それともただ考えすぎているだけなのか、それとも単にスレッド化を警戒しているだけなのかを判断するのは困難です。

ファイルの読み取りとオブジェクトの作成は高速です。1 つの方法は遅いです。依存関係は、連続する各 ctor が前の ctor の結果に依存することです (少し奇妙です) が、それ以外の点ではデータの整合性の問題はないため、ミューテックスなどで保護する必要があるものはないようです。

これが次のようなものよりも複雑なのはなぜですか (粗雑な擬似コード):

while (! eof)
{
    readfile;
    object O(data);
    push_back(O);
    pthread_create(...., O, makeSolid);
}


while(x < vector.size())
{
    pthread_join();
    x++;
}

メインの結合でループしたくない場合は、TID のベクトルを渡すことによって結合を待機するスレッドを生成します。

作成されたオブジェクト/スレッドの数が非常に多い場合は、スレッド プールを使用します。または、実行中のスレッドが結合される前に作成できるスレッドの数を制限する作成ループであるカウンターを配置します。

他のヒント

まず、スレッドの恩恵を受けるには、各スレッドの同様の遅いタスクを見つける必要があります。オブジェクトごとの処理には.5s+かかると言いましたが、ファイルの読み取り /オブジェクトの作成にはどれくらい時間がかかりますか?それは簡単に10分の1または1000分の1になる可能性があります。その場合、マルチスレッドアプローチは怠慢な利益をもたらすでしょう。その場合、(はい、そうでない場合はすぐにあなたの元の質問に答えます)、複数のオブジェクトを同時に処理することを考えてください。処理にかなりの時間がかかると、スレッドの作成オーバーヘッドはそれほど重要ではないため、メインファイルの読み取り/オブジェクト作成スレッドが新しいスレッドを生成し、新しく作成したオブジェクトに向けて配置するだけです。メインスレッドは、後続のオブジェクトの読み取り/作成を続けます。すべてのオブジェクトが読み取り/作成され、すべての処理スレッドが起動されたら、メインスレッドが「結合」(待機する)(待機)します。これがあまりにも多くのスレッド(数千)を作成する場合、メインスレッドが取得できるかどうかに制限を設定します。10個のオブジェクトを読み取り/作成し、5に参加してから、10を読み取り/作成し、10に参加し、読み取り/作成します。 10、終了するまで10などに参加します。

これで、読み取り/作成が処理と並行しているが、処理がシリアル化されるようにしたい場合は、上記のアプローチを使用するが、各オブジェクトの後に結合することができます。このアプローチだけを念頭に置いてこれを設計している場合、それはちょっと奇妙ですが、上記のオブジェクト処理の並列性を簡単に実験できるため、良いことです。

または、メインスレッド(プログラムの開始時にOSが作成する)だけのより複雑なアプローチと、メインスレッドが開始する必要がある単一のワーカースレッドを使用するより複雑なアプローチを使用できます。それらは、Mutex(相互に密接にかかることを保証する変数、つまり、電流ではないことを意味する、データへのアクセスを意味する変数)と、メインスレッドがより多くの作業を提供するまでワーカースレッドが効率的にブロックできるようにする条件変数を使用して調整する必要があります。用語 - ミューテックスと条件変数 - は、Linuxが使用するPOSIXスレッドの標準用語であるため、興味のある特定のライブラリの説明に使用する必要があります。即座に、ワーカースレッドはメインの読み取り/作成スレッドまで待機します。別のオブジェクトが処理の準備ができていることを示すウェイクアップ信号をブロードキャストします。最後に完全に作成された準備が整ったオブジェクトのインデックスを備えたカウンターが必要な場合があります。これにより、ワーカースレッドは、処理されたオブジェクトのカウントを維持し、準備ができているオブジェクトに沿って移動してから、条件変数をもう一度確認できます。

@caleb:かなり - おそらく強調すべきだったでしょう アクティブ スレッド。 GUIスレッドは常に1つと見なす必要があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top