代码之家  ›  专栏  ›  技术社区  ›  bilpor

我如何将一个IEnumerable与一个IEnumerable并行?

  •  3
  • bilpor  · 技术社区  · 8 年前

    我有一个变量:

    var contexts 设置后是 IEnumerable . 此对象的属性之一也是 IEnumerable(IEnumerable) 我有:

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

    但是vs抱怨第二个 ForEach

    1 回复  |  直到 8 年前
        1
  •  3
  •   StuartLC    8 年前

    您试图在这里应用太多嵌套的并行性。

    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 .