如何将For循环更改为PLINQ语法
本文关键字:PLINQ 语法 循环 For | 更新日期: 2023-09-27 18:11:28
我的代码有一个真正的问题,它非常慢,使它无用。我必须交付我的结果下周和这个代码,它需要超过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)
}
}
}
}
为了能够使用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循环的"主体"仍然是并行执行的,没有特定的顺序。当ToList
创建列表时,只有对最终结果进行排序。如果你提到的顺序的重要性意味着你在for循环体中使用了可变状态,那么你将不能使用PLINQ。
这种使用PLINQ的方法不是特别有效。如果您必须处理1,000,000个单元格,那么该代码将分配1,000,000个对象来存储单元格的索引。然而,似乎是处理时间而不是内存分配和垃圾收集限制了你的计算。
如果你使用Parallel.For
之类的东西来并行化你的计算,你可以避免分配的开销,但你将使用TPL而不是PLINQ。
使用下面的代码,您可以使用您的集合代替列表。如果你需要任何帮助,请告诉我:
List<string> lst = new List<string>();
foreach (var item in lst.AsParallel())
{
foreach (var data in item)
{
}
}