1

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

ベクトルが空のときにスレッドを開始する予定でした。それぞれがmakeSolids(下記) を呼び出します。これには、interpDone==true まで実行され、ベクター内のすべてのオブジェクトが処理されるまで実行される while ループがあります。ただし、私はスレッド化に関しては無頓着であり、既製のソリューションを探していました。

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

intel の tbb も見ましたが、parallel_fororを使用するとメインスレッドが停止するように見えまし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
    }
  }
}

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

4

3 に答える 3

1

まず、スレッド化のメリットを得るには、スレッドごとに同様に遅いタスクを見つける必要があります。オブジェクトごとの処理に 5 秒以上かかるとおっしゃいましたが、ファイルの読み取りとオブジェクトの作成にはどれくらいの時間がかかりますか? その時間の 10 分の 1 または 1,000 分の 1 になることは簡単です。その場合は (そうでない場合に備えて、元の質問にすぐに回答します)、複数のオブジェクトを同時に処理することを検討してください。処理にかなりの時間がかかることを考えると、スレッド作成のオーバーヘッドはそれほど重要ではないため、メイン ファイルの読み取り/オブジェクト作成スレッドに新しいスレッドを生成させ、新しく作成されたオブジェクトに向けさせることができます。その後、メイン スレッドは後続のオブジェクトの読み取り/作成を続行します。すべてのオブジェクトの読み取り/作成が完了すると、すべての処理スレッドが起動され、メイン スレッドがワーカー スレッドに「参加」(待機) します。これがあまりにも多くのスレッド (数千) を作成する場合は、メイン スレッドが取得できる距離に制限を設けます。たとえば、10 個のオブジェクトを読み取り/作成し、次に 5 個を結合し、次に 10 個を読み取り/作成し、10 個を結合し、読み取り/作成します。 10、10などを結合して終了します。

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

または、メイン スレッド (プログラムの開始時に OS が作成するスレッド) と、メイン スレッドが開始する必要がある単一のワーカー スレッドのみを含む、より複雑なアプローチを使用することもできます。それらは、ミューテックス (データへの非同時アクセスを意味する相互排他を保証する変数) と、メイン スレッドがさらに作業を提供するまでワーカー スレッドが効率的にブロックできるようにする条件変数を使用して調整する必要があります。用語 - ミューテックスと条件変数 - は、Linux が使用する POSIX スレッドの標準用語であるため、関心のある特定のライブラリの説明で使用する必要があります。別のオブジェクトが処理の準備ができていることを示すウェイクアップ信号をブロードキャストします。

于 2010-09-10T07:46:13.923 に答える
0

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

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

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

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


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

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

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

于 2010-09-10T14:34:28.917 に答える
0

@Caleb:かなり -- おそらく、アクティブなスレッドを強調する必要がありました。GUI スレッドは常に 1 つと見なされます。

于 2010-09-13T08:10:18.597 に答える