C# 修改基准列表时的PLINQ O(n^2)
假设我有一个顺序函数:C# 修改基准列表时的PLINQ O(n^2),c#,multithreading,linq,plinq,C#,Multithreading,Linq,Plinq,假设我有一个顺序函数: private void Process() { for (int i = 0; i < Particles.Count; i++) for (int j = 0; j < Particles.Count; j++) if (check(Particles[i], Particles[j]) { Particle newParticle = Particle.Merge(Particles[i], Parti
private void Process()
{
for (int i = 0; i < Particles.Count; i++)
for (int j = 0; j < Particles.Count; j++)
if (check(Particles[i], Particles[j])
{
Particle newParticle = Particle.Merge(Particles[i], Particles[j]);
Particle p1 = Particles[i];
Particle p2 = Particles[j];
Particles.Remove(p1);
Particles.Remove(p2);
Particles.Add(newParticle);
i = j = 0;
}
}
我得到一个LINQ例外
有什么方法可以并行执行此n^2操作并更改列表的内容吗?请尝试以下方法:
from p1 in Particles.AsParallel()
let collisions = from p2 in Particles
where p1 != p2
where check(p1, p2)
select p2
select Particle.Merge(p1, collisions)
其中第二个粒子.Merge
作用于碰撞列表以生成新粒子。你会希望这里有更多的逻辑,但这会给你一个想法
基本思想是您希望以非破坏性方式创建列表的新副本。然后做任何修改并替换旧列表
您需要做的一些事情是:
- 修改
对列表进行操作:Particle.Merge
李>Particle.Merge(Particle p、 i可数碰撞)
- 添加一些逻辑以防止重复出现在该列表中两次
aspallel()
来实现这一点,以便它/不会/抛出异常。首先,不要对所有和ForEach
使用。使用Select
。当可能存在竞争条件或需要改变集合结构时,应尽量避免对所有
使用。一个更好的解决方案是并行地创建一个新的列表(做起来很便宜,您正在使用引用)并替换旧的列表。如果我有时间完成它,您可能会对我编写的递归PLINQ N体解算器感兴趣。它处理碰撞的方式与我在下面的帖子中描述的完全相同。
from p1 in Particles.AsParallel()
let collisions = from p2 in Particles
where p1 != p2
where check(p1, p2)
select p2
select Particle.Merge(p1, collisions)