有序并行执行

时间:2017-01-25 06:17:31

标签: c# multithreading task-parallel-library parallel.foreach

我有一个像[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]这样的有序列表。我将它传递给Parallel.ForEach声明。我可以以某种方式实现以下桶的执行顺序,例如:处理前3项[1, 2, 3],其中桶本身的排序不是强制性的,例如可以是[2, 1, 3]。然后处理接下来的3个项目[4, 5, 6]等?

2 个答案:

答案 0 :(得分:5)

我不确定你是否可以直接这样做。但我建议你将输入列表分成较小的列表,然后你可以用Parallel.Foreach处理每个子列表。

List<int> fruits = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
List<List<int>> ls = new List<List<int>>();
for (int i = 0; i < fruits.Count; i += 3)
{
    ls.Add(fruits.GetRange(i, Math.Min(3, fruits.Count - i)));
}
foreach (List<int> group in ls)
{
    Parallel.ForEach(group, fruit =>
    {
    });
}

3是小清单的长度。

答案 1 :(得分:2)

即使接受的答案完美地满足要求,也会有一些开销。首先,在我们讨论TPL时,数据阵列的数量可能很大,因此只需创建那么多阵列就非常耗费内存。 此外,@ viveknuna建议的解决方案不保证块的顺序。如果没问题,您可能应该使用@DmitryBychenko的答案进行一次小更新:

const int chunkSize = 3;
var array = Enumerable.Range(1, 9).ToArray();
// get the chunks for indexes for array sized in group of 3
var partitioner = Partitioner.Create(0, array.Length, chunkSize);

// use all the system resources
var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount };

// use the partitioner for a chunks, so outer parallel foreach
// will start a task for all the chunks, [1, 2, 3], [4, 5, 6], [7, 8, 9]
Parallel.ForEach(partitioner, parallelOptions, part =>
    {
        // inner foreach will handle part of the chunk in parallel
        Parallel.ForEach(array.Skip(part.Item1).Take(chunkSize), parallelOptions, value =>
            {
                // handle the array value in parallel
            });
    });

在给定的代码中,如果您将ParallelOptions.MaxDegreeOfParallelism设置为1,您将获得所需的有序并行执行,即chunk chunk。