嵌套的Parallel.ForEach循环在同一个列表中?

Wes*_*sey 12 c# parallel-processing task-parallel-library

我需要并行化一个方法,该方法对列表中的元素进行详尽的成对比较.串行实现很简单:

foreach (var element1 in list)
    foreach (var element2 in list)
        foo(element1, element2);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,foo不会改变element1或element2的状态.我知道简单地执行嵌套的Parallel.ForEach语句是不安全的:

Parallel.ForEach(list, delegate(A element1)
{
    Parallel.ForEach(list, delegate(A element2)
    {
        foo(element1, element2);
    });
});
Run Code Online (Sandbox Code Playgroud)

使用并行任务库实现此目的的理想方法是什么?

Ars*_*nko 15

至少如果你在核心数量至少是列表中项目数量两倍的机器上执行代码,我不确定做嵌入式Parallel.ForEachs 是个好主意.

换句话说,如果您定位四核,并且列表有一千个项,则只需并行化父循环.并行化两个循环不会使代码更快,而是更快,更慢,因为并行任务具有性能成本.

alt text http://www.freeimagehosting.net/uploads/ca97f403f8.png

在每次迭代时,将丢失几毫秒Parallel.ForEach以确定哪个线程必须执行下一次迭代.假设您有一组7项.如果并行化父循环,则这些毫秒将丢失7次.如果你并行化两个循环,它们将丢失7×7 = 49次.设置越大,过热越大.

  • 不要以为PFX会创建与并行任务一样多的线程 - 它比这更聪明. (4认同)

Jou*_*aas 11

难道你不能只有一个平行和一个正常的循环吗?所以要么

Parallel.ForEach(list, delegate(A element1)
{
  foreach(A element2 in list)
    foo(element1, element2)
});

要么

foreach(A element1 in list)
{
  Parallel.ForEach(list, delegate(A element2)
  {
    foo(element1, element2);
  });
}

应该加快速度.无论如何,每个周期永远不会有一个线程,所以这可能与嵌套的并行循环一样快或稍慢.