如何将For循环更改为PLINQ语法?

时间:2014-07-04 05:47:55

标签: c# plinq

我的代码确实存在问题,这个问题非常慢,无法使用。我必须在下周提供我的结果,通过此代码需要超过4周! 由于此代码计算流体运动,我们处理超过100万个单元格。因此,我的主要 For循环(顺序很重要)计算量很大,现在每个输出需要12分钟。 想象一下,我需要至少5000输出!

任何人都可以帮助我提高计算速度吗? 要么 你能帮我理解如何将For循环更改为PLINQ语法吗?

我很沮丧

//implementation of time nt = 1,000,000
    For (int t=0; t<nt; t++)
    { 
// main calculations, 2 dimensional   
    for (int i = 0; i < nx; i++)
        {
            for (int j = 0; j < ny; j++)
            {
                if (!Cells[i, j, 0].IsVirtual)
                {
                    // calculate x velocity - nx = 1,000,000 & ny = 1,000,000
                    // calculate y velocity
                    // Data for each (i,j) affect (i+1,j+1)
            }
         }
     }
    }

2 个答案:

答案 0 :(得分:1)

为了能够使用PLINQ,您需要将二维for循环更改为可以处理的元素序列(例如IEnumerable<T>)。您可以使用以下代码将x和y值创建为序列:

var indices = Enumerable.Range(0, nx).SelectMany(
  _ => Enumerable.Range(0, ny),
 (x, y) => new { X = x, Y = y }
);

然后,您可以使用Where

过滤索引序列
indices.Where(index => !Cells[index.X, index.Y, 0].IsVirtual)

然后,您可以使用Select投影索引以创建结果:

var results = indices
  .Where(...)
  .Select(index => new { index.X, index.Y, Result = ... });

当您将代码转换为此表单并确保它适用于小型数据集时,您可以使用PLINQ通过插入Select并行地在AsParallel中运行计算:

var results = indices
  .Where(...)
  .AsParallel()
  .Select(index => new { index.X, index.Y, Result = ... })
  .ToList();

在你的问题中,你谈到订单的重要性。您可以使用AsOrdered

确保生成的结果与输入索引保持相同的顺序
var results = indices
  .Where(...)
  .AsParallel()
  .AsOrdered()
  .Select(index => new { index.X, index.Y, Result = ... })
  .ToList();

但是,for循环的“body”仍然没有特定的顺序并行执行。只有在ToList创建列表时才会排序的最终结果。如果您提到的订单的重要性意味着您的for循环体中使用了可变状态,那么您将无法使用PLINQ。

这种使用PLINQ的方法并不是特别有效。如果必须处理1,000,000个单元格,则此代码将分配1,000,000个对象来存储单元格的索引。但是,似乎处理时间而不是内存分配和垃圾收集限制了你的计算。

如果您使用类似Parallel.For的内容来并行计算,那么您可以避免分配的开销,但之后您将使用TPL而不是PLINQ。

答案 1 :(得分:-1)

使用下面的代码,您可以使用您的集合代替列表。如果您需要任何帮助,请告诉我:

List<string> lst = new List<string>();
foreach (var item in lst.AsParallel())
{
    foreach (var data in item)
    {

    }
}