23

Parallel.Foreach ループでチャンク パーティショニングを使用する方法と、デフォルトでレンジ パーティショニングを使用する方法を知っている人はいますか。カスタム パーティショナーを作成し、負荷分散を true に設定するだけなので、配列を操作する場合は簡単に思えます。

IEnumerable の要素数は実行時までわからないため、チャンク パーティショニングを機能させる良い方法を見つけられないようです。

どんな助けでも大歓迎です。

ありがとう!

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

4

1 に答える 1

29

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 回答でカバーするには広すぎますが、開始するには MSDN のこのガイドを参照してください。

更新: .NET 4.5 の時点で、Partitioner.Createデータをバッファリングしないオーバーロードが追加されました。これは、範囲の最大サイズが 1 のカスタム パーティショナーを作成するのと同じ効果があります。一連の遅いアイテムが連続して不運になった場合、作業をキューに入れました。

var partitoner = Partitioner.Create(source, EnumerablePartitionerOptions.NoBuffering);
Parallel.ForEach(partitoner, item =>
{
    //Do work
}
于 2013-05-07T19:53:08.667 に答える