有序并行执行
Ordered parallel execution
我有一个像 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
这样的有序列表。我将它传递给 Parallel.ForEach
语句。我能否以某种方式实现以下存储桶的执行顺序,例如:处理前 3 个项目 [1, 2, 3]
,其中存储桶本身的排序不是强制性的,例如可以是 [2, 1, 3]
。然后处理接下来的 3 项 [4, 5, 6]
,等等?
我不确定您是否可以直接执行此操作。但我建议您将输入列表分成较小的列表,然后您可以使用 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是小列表的长度。
即使接受的答案完全满足要求,也有一些开销。首先,我们说的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
设置为 1
,您将获得所需的有序并行执行,一个块一个块地执行。
我有一个像 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
这样的有序列表。我将它传递给 Parallel.ForEach
语句。我能否以某种方式实现以下存储桶的执行顺序,例如:处理前 3 个项目 [1, 2, 3]
,其中存储桶本身的排序不是强制性的,例如可以是 [2, 1, 3]
。然后处理接下来的 3 项 [4, 5, 6]
,等等?
我不确定您是否可以直接执行此操作。但我建议您将输入列表分成较小的列表,然后您可以使用 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是小列表的长度。
即使接受的答案完全满足要求,也有一些开销。首先,我们说的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
设置为 1
,您将获得所需的有序并行执行,一个块一个块地执行。