2

基本的に、アイテムのリストを一度に 1 つずつではなく、複数のスレッドで処理したいと考えています。一度に実行できるスレッド数を制限したい。このアプローチは理にかなっていますか?スレッド数にグローバル変数を使用することが唯一のオプションですか? (以下の疑似コード)

foreach item in list
    while thread_count >= thread_max
        sleep
    loop
    start_thread item
    thread_count++
next

function start_thread(item)
    do_something_to item
    thread_count--
end function
4

2 に答える 2

6

これには PLINQ を使用し、次のように最大並列度を指定します。

生のリストを直接処理したいだけで、他のフィルタリングやマッピング(Where / Select)を行っていないことに気付いたので、実際にこれに対する答えを変更しています。この特定のケースでは、Parallel::ForEach を使用し、次のように ParallelOptions を介して MaxDegreeOfParallelism を指定することをお勧めします。

 int myMaxDegreeOfParallelism = 4; // read this from config maybe

 Parallel.ForEach(
    list,
    new ParallelOptions
    {
        MaxDegreeOfParallelism = myMaxDegreeOfParallelism
    }
    item =>
    {
        // ... your work here ...
    });

ここで、このように最大値を指定すると、リソースが使用可能であっても、PLINQ がこれ以上リソースを使用できなくなることに注意してください。したがって、これが 8 コアのマシンで実行された場合、4 コア以上を使用することはありません。逆に、4 を指定したからといって、常に 4 が同時に実行されることが保証されているわけではありません。それはすべて、TPL が最適化するために使用しているいくつかのヒューリスティックに依存します。

于 2011-03-03T00:51:09.530 に答える
1

これは理にかなっていますが、非常に具体的なパフォーマンス上の理由がある場合や .NET 3.5 で行き詰っている場合を除き、これが通常の方法ではないことを認識していただければ幸いです。通常、リスト内の要素に対して を使用し、パーティParallel.ForEachショナーに依存して作業を適切なチャンクに分割します。

TPL を持っていなかったとしても、スレッドが終了した瞬間に少しずつ作業を行うよりも、すべての作業を分割して各スレッドに一度に大量の作業を渡す方が慣用的です。自分のやり方で行う唯一の理由は、特定の作業項目にかかる時間が多かれ少なかれ予測不可能であると予想され、事前に十分に作業を分割できなかった場合です。

(また、スレッドへの参照を保持して、まだ動作中のスレッドと完了したスレッドの数を確認することもできます。これにより、変数が不要になります。)

于 2011-03-02T22:08:02.823 に答える