Parallel.ForEach在MaxDegreeOfParallelism=1时会按顺序处理吗?

11
使用 MaxDegreeOfParallelism==1Parallel.ForEach() 方法是否保证按顺序处理输入的可枚举对象?
如果答案是否定的,有没有方法可以强制执行此行为?

5
我可以问一下你为什么想知道这个吗?只是学术好奇心,还是你遇到了某种现实问题? - mason
2
如果你的测试代码需要按顺序处理一些在实际情况下不是按顺序的东西,那么你的测试就有缺陷。重写它,使验证结果不依赖于这个假设,或者重写被测试的代码,在 MaxDegreeOfParallelism 为1时做出明确的异常,这样你就可以确保它在所有情况下的一致行为。显然,第一种选择更可取。 - Jeroen Mostert
1
有趣的问题!也许答案可以在.NET源代码中找到?https://referencesource.microsoft.com/#mscorlib/system/threading/Tasks/Parallel.cs,ecf3d8a35545d82b - l33t
1
Parallel.ForEach()MaxDegreeOfParallelism==1 有什么意义呢?这似乎只是浪费时间。 - Liam
3
查看源代码或运行测试并不能告诉你未来的实现情况。你需要在文档中找到明确的声明。 - H H
显示剩余6条评论
3个回答

16
首先,Microsoft有关并行编程的官方文档指出执行顺序无法保证是正确的。

Parallel.ForEach方法不能保证执行顺序。与顺序ForEach循环不同,传入的值不总是按顺序处理。

最好按照公共API的设计使用Parallel.ForEach以并行方式处理项目。如果需要按顺序处理项目,则最好使用常规的foreach循环。这比使用MaxDegreeOfParallelism = 1更清晰。

话虽如此,出于好奇,我查看了.NET 4.7.1的源代码。简而言之,如果MaxDegreeOfParallelism = 1,则项目将按顺序处理。但是,您不应该依赖此功能进行未来实现,因为可能不总是这样。

  1. 查看Parallel.ForEach并跟随它,最终会看到要迭代的集合被分区(如果是TSource[]List<TSource>IEnumerable<TSource>,此过程略有不同)。

  2. ParallelForReplicaTask中覆盖了Task.SavedStateForNextReplicaTask.SavedStateFromPreviousReplica,以便在并行运行的任务之间通信状态。在本例中,它们用于通信任务应迭代哪个分区。

  3. 最后,让我们来看一下 Task.ExecuteSelfReplicatingParallelForReplicatingTask 根据指定的并行度以及任务调度程序的 MaximumConcurrencyLevel 来覆盖 ShouldReplicate。 因此,当 MaxDegreeOfParallelism = 1 时,只会创建一个子任务。因此,此任务仅在创建的单个分区上运行。

所以,回答您的问题:截至目前,MaxDegreeOfParallism = 1Parallel.ForEach 将从头到尾枚举 TSource[]、从头到尾枚举 IList<TSource>,以及对于 IEnumerable<TSource>,使用GetEnumerator,具体取决于 IEnumerable<TSource> 是否可以转换为 OrderablePartitioner<TSource>。这三个路径在Parallel.ForEachWorker中确定。

我强烈鼓励您自己浏览源代码,以便亲眼看到。

我希望这能回答您的问题,但重要的是要记住:不要依赖这个。未来这个实现可能会发生变化。


4

-1
答案是“不行”,但您可以使用下面所示的AsOrdered()强制执行该行为。
using System;
using System.Linq;
using System.Threading.Tasks;

var items = Enumerable.Range(0, 1000).ToArray();
Parallel.ForEach(items.AsParallel().AsOrdered(),
    new ParallelOptions { MaxDegreeOfParallelism = 1 },
    Console.WriteLine);

SharpLab 示例 在这里

显然,如果你增加 MaxDegreeOfParallelism,每个并行任务将处理其 (或 )的项目 - 按照它们在原始 有序 列表中出现的顺序。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接