假设我有这个顺序函数:
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 操作并能够更改列表的内容?