我有一个变量:
var contexts
设置后为IEnumerable
。此对象的其中一个属性也是IEnumerable
我有:
Parallel.ForEach(contexts.AsParallel(), (context) =>
{
Parallel.ForEach(context, (child) =>
{
});
});
但VS抱怨第二个ForEach
答案 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
。