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

C# 如何将For循环更改为PLINQ语法?,c#,plinq,C#,Plinq,我有一个真正的问题,我的代码是非常缓慢,使它无用。我必须在下周提交我的结果,按照这段代码,它需要超过4周的时间! 在这段代码计算流体运动时,我们处理了100多万个细胞。因此,我的主要For loops(顺序很重要)计算量很大,现在每个输出需要12分钟。 假设我需要至少5000个输出 有人能帮我提高计算速度吗? 或 您能帮助我了解如何将For loop更改为PLINQ语法吗? 我很沮丧 //时间nt=1000000的实现 对于(int t=0;t使用以下代码,您可以使用您的收藏列表。如果您需要任何

我有一个真正的问题,我的代码是非常缓慢,使它无用。我必须在下周提交我的结果,按照这段代码,它需要超过4周的时间! 在这段代码计算流体运动时,我们处理了100多万个细胞。因此,我的主要For loops(顺序很重要)计算量很大,现在每个输出需要12分钟。 假设我需要至少5000个输出

有人能帮我提高计算速度吗? 或 您能帮助我了解如何将For loop更改为PLINQ语法吗?

我很沮丧

//时间nt=1000000的实现

对于(int t=0;t使用以下代码,您可以使用您的收藏列表。如果您需要任何帮助,请告诉我:

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

    }
}
List lst=new List();
foreach(lst.AsParallel()中的变量项)
{
foreach(项目中的var数据)
{
}
}

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

var indices = Enumerable.Range(0, nx).SelectMany(
  _ => Enumerable.Range(0, ny),
 (x, y) => new { X = x, Y = y }
);
然后,您可以使用
过滤索引序列,其中

indices.Where(index => !Cells[index.X, index.Y, 0].IsVirtual)
然后,您可以使用
选择
,投影索引以创建结果:

var results = indices
  .Where(...)
  .Select(index => new { index.X, index.Y, Result = ... });
当您将代码转换成这种形式并确保它在一个小数据集上工作时,您可以使用PLINQ在
Select
中通过插入
aspallel
并行运行计算:

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循环的顺序仍然是并行执行的,没有特定的顺序。只有当列表由
ToList
创建时,才会对最终结果进行排序。如果您提到的顺序的重要性意味着您的for循环体中使用了可变状态,那么您将无法使用PLINQ

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


如果您使用类似于并行计算的方法,您可以避免分配的开销,但是您将使用TPL而不是PLINQ。

第一个问题是,计算是否可以并行进行,正如您提到的,顺序很重要,那么一个贯穿循环是否会影响下一次运行?同时,花费的大部分时间在哪里,t实际计算还是访问对象进行计算代码非常大,但大多数计算是在两个For循环和每个输出中进行的(它有一个更大的For循环,一次工作一次)应该执行这两个内部For循环。这些For循环计算100万点的速度。其他For循环对速度没有影响。您是否有分析当前实现的热门路径?使用并行处理可以提供边际加速,但优化实际实现可能会产生额外的改进元素。你确定每个内部部分独立于其他内部部分吗?我同意@GregC,也许你的算法是问题,而不是实现。你看过解决问题的数值方法吗?嗨,事实上,我不明白你的评论什么是“nx”在你的代码中,或者给我整个代码,我将把它转换成plinq。我的代码中速度最慢的主要部分是前面提到的两个For循环。nx=1000000-ny=1000000,而For循环中有很大一部分是速度计算。谢谢你的回答。For循环应该是有序的,因为每次迭代的结果都是必需的sary为下一次迭代做准备。所以它们应该一个接一个地完成。这样我就不能使用TPL和PLINQ。那么我应该做什么来提高速度呢?@user3803849:很难说,因为我没有关于你的计算的信息。要并行化你的计算,你需要在逻辑上找到一种方法来划分工作,以便多个线程可以完成parallel.TPL和PLINQ只能在您找到划分工作的方法后才能帮助您完成工作。它无法神奇地为您提供此划分。如果您意识到您的算法要求严格按顺序处理单元格,您可能会转而专注于优化for循环内的计算。my calculat离子是这样的,例如速度(i,j)需要计算速度(i+1,j+1)。所以一切都应该井然有序。我的代码需要时间,因为它需要计算非常多的点和这么多的时间。例如,对于一个有100万个细胞(二维细胞)的系统,至少需要1000万次我怎样才能优化这种计算?我的一些C++编写的朋友使用GPU实现加速计算。如果你的要求是按顺序计算行,你可以使用一个正常的for循环来循环这个循环中的行,你可以有一个“并行”。对行中的单元使用TPL或PLINQ进行循环。因为行中的单元数远大于核心数,所以您仍然可以获得核心的最大利用率。
var results = indices
  .Where(...)
  .AsParallel()
  .AsOrdered()
  .Select(index => new { index.X, index.Y, Result = ... })
  .ToList();