3

アプリケーション用のスレッドプールが必要であり、標準 (C++11 またはブースト) のものにできるだけ依存したいと考えています。基本的に必要なものを解決する非公式の(!)ブーストスレッドプールクラスがあることに気付きましたが、ブーストライブラリ自体にないため、避けたいと思います-なぜコアライブラリにまだないのですか?長年?

このページや他の場所のいくつかの投稿では、boost::asio を使用してスレッドプールのような動作を実現することを提案しています。一見、それは私がやりたいことのように見えましたが、私が見たすべての実装には、現在アクティブなタスクに参加する手段がないことがわかりました。そのため、私のアプリケーションでは役に立ちません。結合を実行するために、すべてのスレッドに停止シグナルを送信し、その後それらを結合します。ただし、それは私のユースケースでのスレッドプールの利点を完全に無効にします。これは、新しいタスクで新しいスレッドの作成が必要になるためです。

私がやりたいことは次のとおりです。

ThreadPool pool(4);
for (...)
{
    for (int i=0;i<something;i++)
        pool.pushTask(...);
    pool.join();
    // do something with the results
}

誰でも解決策を提案できますか (sourceforge で既存の非公式スレッド プールを使用する場合を除く)。ここで私を助けることができるC++ 11またはコアブーストに何かありますか?

4

4 に答える 4

3

一見、やりたいことのように見えましたが、これまでに見たすべての実装には、現在アクティブなタスクに参加する手段がないため、アプリケーションには役に立たないことがわかりました。結合を実行するために、それらはすべてのスレッドに停止信号を送信し、その後それらを結合します。ただし、これにより、新しいタスクで新しいスレッドを作成する必要があるため、私のユースケースではスレッドプールの利点が完全に無効になります。

asioの例を誤解しているかもしれません。

IIRC(そしてしばらく経ちました)スレッドプールで実行されている各スレッドが呼び出しましio_service::runた。これは、事実上、各スレッドにイベントループとスケジューラーがあることを意味します。次に、asioにタスクを完了させるにはio_service、io_service :: postメソッドを使用してタスクをPOSTし、残りはasioのスケジューリングメカニズムが処理します。を呼び出さない限りio_service::stop、スレッドプールは、実行を開始したのと同じ数のスレッドを使用して実行を継続します(各スレッドに実行する作業があるか、io_service::workオブジェクトが割り当てられていると想定します)。

したがって、新しいタスクのために新しいスレッドを作成する必要はありません。これは、スレッドプールの概念に反します。

于 2012-10-24T18:49:15.213 に答える
1

「OnCompletion(task)」メソッド/イベントを持つタスクから各タスク クラスを派生させます。スレッドプール スレッドは、タスクのメインの run() メソッドを呼び出した後にそれを呼び出すことができます。

1 つのタスクが完了するのを待つのは簡単です。OnCompletion() は、元のスレッドにシグナルを送る、condvar にシグナルを送る、プロデューサー/コンシューマー キューにタスクをキューに入れる、SendMessage/PostMessage API を呼び出す、Invoke/BeginInvoke など、何でも実行できます。

元のスレッドがいくつかのタスクがすべて完了するのを待つ必要がある場合は、上記を拡張して、単一の「待機タスク」をプールに発行できます。待機タスクには、他のタスクの完了を通知するための独自の OnCompletion があり、発行される「メイン」タスクの数に設定されたスレッドセーフな「タスク カウンター」(アトミック ops またはロック) があります。最初に待機タスクがプールに発行され、それを実行するスレッドが待機タスクのプライベート 'allDone' condvar で待機します。次に、「メイン」タスクがプールに発行され、OnCompletion が設定されて、タスク カウンターをゼロに向けて減少させる待機タスクのメソッドが呼び出されます。タスク カウンターがゼロに達すると、これを達成したスレッドが allDone condvar を通知します。その後、待機タスク OnCompletion が実行され、すべてのメイン タスクの完了が通知されます。

このようなメカニズムは、スレッドプール スレッドの継続的な作成/終了/結合/削除を必要とせず、元のタスクにシグナルを送信する必要がある方法に制限を設けず、そのようなタスク グループを必要な数だけ発行できます。ただし、各待機タスクは 1 つのスレッドプール スレッドをブロックすることに注意してください。そのため、プールに追加のスレッドをいくつか作成するようにしてください (通常は問題ありません)。

于 2012-10-14T10:31:57.687 に答える
1

これはboost::futuresの仕事のようです。ドキュメントの例は、あなたが何をしようとしているのかを正確に示しているようです。

于 2012-10-24T17:22:15.303 に答える
0

スレッドに参加するということは、スレッドが停止するまで停止することを意味し、スレッドが停止して新しいタスクを割り当てたい場合は、新しいスレッドを作成する必要があります。boost::condition_variableしたがって、あなたの場合、タスクの終了を示す条件 (たとえば ) を待つ必要があります。boost::asioしたがって、この手法を使用すると、と を使用して実装するのは非常に簡単boost::condition_variableです。各スレッド呼び出しboost::asio::io_service::runとタスクはスケジュールされ、異なるスレッドで実行され、最後に、各タスクは aboost::condition_variableまたはイベント デクリメント aを設定しstd::atomicて、ジョブの終了を示します! それは本当に簡単ですね。

于 2012-10-14T09:40:23.793 に答える