4

Visual Studio 2010 の Parallel Patterns Library (PPL) を使用Concurrency::parallel_for()して、インデックス付きの一連のタスクを処理しています (通常、インデックス セットは、同時に実行できるスレッドの数よりもはるかに大きくなります)。各タスクは、長い計算を行う前に、共有リソース マネージャーからプライベート作業ストレージ リソースを要求することから始めます (例: タスク固有のメモリ マップ ファイルのビューですが、各タスクが共有ヒープからのプライベート メモリ割り当てを要求しました)。

共有リソース マネージャーの使用は と同期され、Concurrency::critical_sectionここから問題が始まります。最初のスレッド/タスクがクリティカル セクションにあり、2 番目のタスクが要求を行う場合、最初のタスクの要求が処理されるまで待機する必要があります。PPL はどうやら次のように考えます: このスレッドは待機中であり、実行するタスクが他にもあるため、別のスレッドが作成され、ほとんどが同じリソース マネージャーで最大 870 のスレッドを待機させます。

リソース要求の処理はタスク全体のほんの一部にすぎないので、その部分で PPL に馬を保持するように伝えたいと思います。 working-thread とここでの私の質問は、特定のスレッドセクションが協調的にブロックされていても、特定のスレッドセクションが新しいスレッドを作成するのを防ぐことができるかどうか、およびその方法です。スレッドの処理パスのさらに下にある他のブロックで新しいスレッドが作成されることは気にしませんが、(ハイパー) コアの数の 2 倍にすぎません。

これまでに検討した代替案:

  1. タスクをキューに入れ、限られた数のスレッドからキューを処理します。問題: 私は、PPL の parallel_for が単独でそれを行うことを望んでいました。

  2. を定義しConcurrency::combinable<Resource> resourceSetます。(リソースを再利用することにより) リソース要求の数をスレッドの数 (タスクの数より少なくする必要があります) に減らすために、一度Concurrency::parallel_for初期化します。resourceSet.local()問題: この最適化では、余分なスレッドの作成が妨げられません。

  3. parallel_forループ外の各タスクに必要なリソースを事前に割り当てます。問題: これはあまりにも多くのシステム リソースを要求しますが、リソースの量をスレッド/コアの数に制限しても問題ありません (それが爆発しない場合)。

http://msdn.microsoft.com/en-us/library/ff601930.aspxのセクション「並列ループで繰り返しブロックしない」を読みましたが、ここのアドバイスに従うと、並列スレッドがまったく発生しません。

4

2 に答える 2

4

協調同期を使用しないように PPL/ConcRT を構成できるかどうか、または少なくとも作成するスレッドの数に制限を設けることができるかどうかはわかりません。スケジューラ ポリシーで制御できるのではないかと思ったのですが、どのポリシー パラメータも目的に合っていないようです。

ただし、理想的な方法でなくても、問題を軽減するのに役立つと思われるいくつかの提案があります。

  • の代わりにcritical_section、非協調的な同期プリミティブを使用して、リソース マネージャーを保護します。(チェックはしていませんが) 従来のWinAPICRITICAL_SECTIONは成功するはずだと思います。この方向への急進的なステップとして、コード用に他の並列ライブラリを検討することもできます。たとえば、Intel の TBB は PPL API のほとんどを提供し、さらに多くの API を提供します(免責事項: 私はそれと提携しています)。

  • 並列ループの外側に多数のリソースを事前に割り当てます。タスクごとに 1 つのリソースは必要ありません。スレッドごとに 1 つで十分です。これらのリソースを に入れconcurrent_queue、タスク内でリソースをキューからポップし、使用してからプッシュバックします。また、スレッドはリソースをキューに戻す代わりにcombinable、他のタスクで再利用するためにオブジェクト内に保持する場合があります。キューがたまたま空になった場合 (たとえば、PPL がマシンをオーバーサブスクライブした場合)、別のアプローチがあるかもしれません。たとえば、他のスレッドがリソースを返すまでループでスピンしたり、マネージャーから別のリソースを要求したりします。また、リソースが枯渇する可能性を最小限に抑えるために、スレッド数よりも多くのリソースを事前に割り当てることもできます。

于 2014-09-30T21:27:18.560 に答える
1

私の答えは PPL を使用した「解決策」ではありませんが、 taskqueueのようなスレッド プールを使用すると簡単に実行できると思います。この回答を参照してください。

したがって、キューを作業でいっぱいにすると、並行して作業するタスクが「x」個を超えないようになります。ここで、x はboost::thread::hardware_concurrency()(はい、もう一度ブーストします...)

于 2014-10-01T14:26:31.540 に答える