2016-09-26 16 views
2

の終わりに向かって遅くなりますアイテムの最初の80%は大丈夫です - すべてのCPUコアを使用して非常にいいです。Parallel.ForEachは、私は次の問題を持って反復

反復が終わりに近づいているように見える(約80%私は言うだろう)スレッドの数がコアによってコアを下り始めるのを見て、最後に&最後のアイテムの約5%が2つのコアによってのみ処理されます。したがって、すべてのコアを最後まで使用するように促されると、繰り返しの終わりに向かってかなり遅くなります。

ワークロードはアイテムごとに非常に異なることに注意してください。 1つは1-2秒続くことができ、他の項目は2〜3分かかることがあります。

いずれかのご意見、ご提案は大歓迎です。使用

コード:

var source = myList.ToArray(); 
var rangePartitioner = Partitioner.Create(0, source.Lenght); 
using (SqlConnection connection =new SqlConnection(cnStr)) 
{ 
    connection.Open(); 
    try 
    (
     Parallel.ForEach(rangePartitioner, (range, loopState) => 
     { 
     for(int i = range.Item1; i<range.Item2; i++) 
     { 
      CPUIntensiveMethod(source[i]); 
     } 
     }); 
    } 
    catch(AggretateException ae) 
    { //Exception cachting} 
} 
+0

することができこのコードと関係がありますか? *単一の*接続でSQL文を「並列」で実行しようとしていますか?なぜ「並列実行」がSQLパフォーマンスの問題に役立つと思いますか? –

+0

私はマルチスレッドの単一の接続を使用しません。接続はプールされます。スレッドごとに接続を作成する必要があります。 –

+0

CPUコアの数に等しい最大並列度を適用してください: 'Parallel.ForEach(...、ParallelOptions {MaxDegreeOfParallelism = Environment.ProcessorCount} ...)' –

答えて

0

これは、並列処理は、計算あたりであることの避けられない結果です。全体の並列バッチは、ワークセット内の最も遅い単一の項目が取った時間よりも速く実行することはできません。


100の遅い8その項目、(1000たとえば実行するため)、残りのバッチを想像してみては(実行するために1秒を言う)迅速です。 8つのスレッドにわたってランダムな順序でそれらを蹴飛ばします。最終的に各スレッドは長時間実行されているアイテムの1つを計算することになり、この時点で完全な利用が見られます。最終的には、長いオペレーションを打ったオペレータは長いオペレーションを終え、残りの短いオペレーションをすばやく終了します。その時点では、長い稼働中の作業者しか待機していないので、アクティブな稼働率が低下していることがわかります。つまり、ある時点では3オープの作業が残っているため、3つのコアしか使用されていません。


緩和タクティクス

  • あなたの長時間実行されているアイテムは、彼らがより速く下限ランタイムを持ってできるようにする「内部並列性」に影響を受けやすいかもしれません。
  • あなたの長時間実行されているアイテムは
  • (あなたが可能な限りの完全なCPU使用率を取得することを確認します)識別し、最初に起動するために優先順位を付けることができる場合があります(下記の更新を参照)、本体のケースでDONT使用パーティショニングを長く実行することができます。これは単にこの効果の「ヒット」を増加させるためです。 (つまり、rangePartitionerを完全に削除する)。これにより、このエフェクトが特定のループに及ぼす影響が大幅に軽減されます。

バッチ実行時は、バッチ内の最も遅い項目の実行時に制限されます。


更新は、私はまた、あなたが大規模なこの効果の範囲を増加させ、あなたのループ、上のパーティショニングを使用している気づいている、あなたは「この作品セットNのワークセットにダウンを破る」と言っている。すなわち、その後、それらのN個のワークセットの実行を並列化します。上記の例では、これは、長い作業のうち3つを同じワークセットに(つまり)取得し、同じスレッド上で処理することを意味する可能性があります。そのため、体内が長時間走れる場合は、にはを使用してください。例えば、ここでパーティショニングhttps://msdn.microsoft.com/en-us/library/dd560853(v=vs.110).aspxこれを言っているのドキュメントは短い体

0

あなたが項目ごとの同じ数を処理する複数のスレッドを持っており、各項目は、時間の変化量を要する場合は、もちろん、あなたが持っているだろうことを目的としています先に終了するスレッドがあります。

あなたはそのサイズが知られていないコレクションを使用する場合は、アイテムを1つずつ行われます:

var source = myList.AsEnumerable(); 

別のアプローチは、あなたが何をしようとしている生産者 - 消費者パターン
https://msdn.microsoft.com/en-us/library/dd997371

関連する問題