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

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

foreach (var element1 in list) foreach (var element2 in list) foo(element1, element2); 

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

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

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

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

  Parallel.ForEach(list,delegate(A element1)
 {
   foreach(列表中的元素2)
     foo(element1,element2)
 }); 

要么

  foreach(列表中的元素1)
 {
   Parallel.ForEach(list,delegate(A element2)
   {
     foo(element1,element2);
   });
 } 

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

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

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

alt text http://sofzh.miximages.com/c%23/www.freeimagehosting.net

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

这两个嵌套循环本质上意味着你想要自己吸引列表的cartessian产品。 您可以通过首先在临时列表中创建所有对,然后使用Parallel.ForEach迭代该列表来并行化整个操作。

编辑 :您可以使用迭代器返回组合的2元素元组,而不是创建所有组合的列表。 Parallel.ForEach仍将并行处理元组。

下面的示例打印出当前的迭代步骤,以显示结果无序返回,正如在并行处理期间所预期的那样:

  const int SIZE = 10; static void Main(string[] args) { List list = new List(SIZE); for(int i=0;i Console.WriteLine("{0},{1},{2}",l,t.Item1,t.Item2)); } static IEnumerable> GetCombinations(List list) { for(int i=0;i