Parallel.ForEach需要使用AsParallel()吗?

19

ParallelEnumerable有一个静态成员AsParallel。如果我有一个IEnumerable<T>并想使用Parallel.ForEach,这是否意味着我应该始终使用AsParallel

例如,下面两个示例(其他一切相等)都正确吗?

不使用AsParallel

List<string> list = new List<string>();
Parallel.ForEach<string>(GetFileList().Where(file => reader.Match(file)), f => list.Add(f));

或者使用 AsParallel

List<string> list = new List<string>();
Parallel.ForEach<string>(GetFileList().Where(file => reader.Match(file)).AsParallel(), f => list.Add(f));
1个回答

23

这取决于被调用的内容,它们是不同的问题。

.AsParallel() 并行化枚举而不是任务的委派。

Parallel.ForEach 并行化了循环,为每个元素分配任务到工作线程中执行。

因此,除非你的源枚举从变成并行获益(例如,reader.Match(file) 的开销很大),它们是相等的。对于您最后的问题,是的,两种方法也都是正确的。

另外,还有一种构造方式可以让代码变得更简洁,同时仍能最大限度地发挥PLINQ的优势:

GetFileList().Where(file => reader.Match(file)).ForAll(f => list.Add(f));

2
嗯...并行枚举到底是什么?或者至少如何将该并行化与任务委派分开? - dkackman
3
@dkackman .AsParallel()准备了用于并行执行的枚举,特别是在这种情况下是.SelectMany()的并行版本。想象一下一个有繁重Where子句但没有顺序的枚举,我们可以通过尽可能多地在多个内核上同时评估where子句,将下一个枚举传递给下一个可用线程,从而使其快近 n 倍。之后我们处理该结果的方式也可以以相同的方式处理,即在一个线程中同步处理或根据可用协处理器分布处理,这就是Parallel.ForEach.ForAll部分。明白了吗? - Nick Craver
那很有道理。谢谢Nick。 - dkackman

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