首页 > 解决方案 > C# 如何并行化 IEnumerable 的 IEnumerable?

问题描述

我有一个变量:

var contexts设置后的位置是IEnumerable. 这个对象的属性之一也是IEnumerable我拥有的:

Parallel.ForEach(contexts.AsParallel(), (context) =>
{
    Parallel.ForEach(context, (child) =>
    {

    });
});

但是VS抱怨第二个ForEach

标签: c#parallel-processing

解决方案


您正在尝试在这里应用太多嵌套并行性。

Parallel.ForEach(   <-- #1
     contexts.AsParallel(), <-- #2
         (context) =>  {
        Parallel.ForEach( <- #3

假设这是 CPU 绑定的工作,你真的不想这样做。这可能会创建太多需要映射到线程的任务,这将导致大量适得其反的上下文切换。

假设在最外层循环有足够数量的项目且体积相等,那么最好只在外层循环保持并行性:

Parallel.ForEach(
  contexts, 
  context => { ...

(如果外层循环的项目数量不足以让所有核心保持忙碌,或者如果内层的项目分散IEnumerable不均匀,会导致任务在不相等的时间完成,那么可以考虑使用@TheGeneral的使用思想contexts.SelectMany(c => c),即形式outer.SelectMany(o => o.Inner),在并行化之前将嵌套集合展平为一个更大的集合)。

如果您仍然发现并发性对于 CPU 密集型工作来说太高,您可以将其与目标计算机上的实际内核数相匹配,例如,如果您有 8 个可用内核:

Parallel.ForEach(
  contexts, 
  new ParallelOptions { MaxDegreeOfParallelism = 8 },  
  context => { ...

但是,如果这将用于 IO 绑定工作,那么Parallel.For*/.AsParallel是错误的工具 - 使用异步并行工具,例如Task.WhenAll.


推荐阅读