2013-05-07 14 views
18

Parallel.Foreachループでチャンク分割を使用する方法を知っている人はいませんか?デフォルトでは範囲分割が考えられます。配列を使って作業するときは、カスタムパーティショナーを作成し、ロードバランシングをtrueに設定するだけなので、簡単です。Parallel.Foreachのチャンク分割IEnumerable

IEnumerableの要素の数がランタイムまでわからないので、チャンク分割を機能させるための良い方法を見つけることができないようです。

ご協力いただければ幸いです。

ありがとうございました!

私が各オブジェクトで実行しようとしている作業は、実行に大きく異なる時間がかかります。最後には、通常、最後のスレッドが作業を完了するまでに何時間も待っています。私が達成しようとしているのは、各スレッドにアイテムを事前に割り当てる代わりに、並列ループがチャンクを途中で要求することです。

+0

なぜこれが(興味のある) –

+0

チャンクかチャンクごとのサイズでチャンクアップしますか? – SimpleVar

+0

IEnumerableを持っていますか、またはインデクサーを実装していますか(これで 'obj [i]'を実行できますか?)あなたがインデックスを渡すことができれば私は解決策を持っています。 –

答えて

19

あなたのIEnumerableは本当にインデクサーを持っていた何か(つまり、あなたがアイテムを出すためにobj[1]を行うことができます)、それはあなたが書く必要があることを行うことができない場合は、しかし、次の

var rangePartitioner = Partitioner.Create(0, source.Length); 
    Parallel.ForEach(rangePartitioner, (range, loopState) => 
    { 
     // Loop over each range element without a delegate invocation. 
     for (int i = range.Item1; i < range.Item2; i++) 
     { 
      var item = source[i] 
      //Do work on item 
     } 
    }); 

を行うことができた場合System.Collections.Concurrent.Partitioner<TSource>から派生した新しいクラスを作成してカスタムパーティショナーを作成します。その件名は余りに広すぎてSOの答えでカバーすることはできませんが、開始するにはthis guide on the MSDNをご覧ください。

UPDATE:彼らはデータをバッファリングしないPartitioner.Create過負荷を追加 .NET 4.5の時点で、それはあなたが得ることはありませんこれで1の範囲の最大サイズとカスタムパーティショナーを作るのと同じ効果があります1つのスレッドは、一連の遅い項目が残っていると不運になってしまった場合には、キューに入れられた作業がたくさんあります。

var partitoner = Partitioner.Create(source, EnumerablePartitionerOptions.NoBuffering); 
Parallel.ForEach(partitoner, item => 
{ 
    //Do work 
} 
関連する問題