gpt4 book ai didi

c# - 修改基础列表时的 PLINQ O(n^2)

转载 作者:行者123 更新时间:2023-11-30 17:57:08 26 4
gpt4 key购买 nike

假设我有这个顺序函数:

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;
}
}

那么这有什么作用呢?它检查两个粒子是否应该合并。如果应该,则创建一个新粒子,从列表中删除原始粒子,并将新粒子添加到列表中。

然后我通过将 i 和 j 设置为零来做一些懒惰的事情。在单个 for 循环中,我可以只使用 Particles.RemoveAt(i--) 并且循环将从它停止的地方继续,但是因为这里我们有 i 和 j 它是复杂得多。

无论如何。这是另一个应该很容易并行化的代码块。唯一的问题是我需要修改我正在迭代的集合,无论它是并行的还是顺序的。

如果我使用 foreach 而不是 for,我会收到一个异常,指出集合的大小已更改。如果我使用 PLINQ:

private void Process()
{
Particles.AsParallel.ForAll(p1 =>
{
Particles.ForEach(p2 =>
{
if (check(p1, p2)
{
Particle newParticle = Particle.Merge(p1, p2);

Particles.Remove(p1);
Particles.Remove(p2);
Particles.Add(newParticle);
}
});
});
}

我得到一个 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)

第二个在哪里Particle.Merge作用于碰撞列表以生成新的粒子。你会想要比这更多的逻辑,但这应该给你一个想法。

基本思想是您想要非破坏性地创建列表的新副本。然后做任何修改并替换旧列表。

您需要做的一些事情是:

  • 修改Particle.Merge对列表进行操作:Particle.Merge(Particle
    p, IEnumerable<Particle> collisions)
    .
  • 添加一些逻辑以防止重复项在该列表中出现两次。

关于c# - 修改基础列表时的 PLINQ O(n^2),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13446555/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com