C#我如何平行IEnumerable的IEnumerable?

时间:2018-05-30 08:54:33

标签: c# parallel-processing

我有一个变量:

var contexts设置后为IEnumerable。此对象的其中一个属性也是IEnumerable我有:

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

    });
});

但VS抱怨第二个ForEach

1 个答案:

答案 0 :(得分:3)

你试图在这里应用过多的嵌套并行性。

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