Пусть у меня есть ряд Particle
с в X, Y пространство, и я хочу, чтобы нормализовать их все так, чтобы среднее X и Y равны 0.PLINQ AsParallel(). ForAll() доступа ресурс
Последовательная реализация :
public void Normalise()
{
double avgX = 0.0;
double avgY = 0.0;
foreach (Particle p in Particles)
{
avgX += p.X;
avgY += p.Y;
}
avgX /= (double)Particles.Count;
avgY /= (double)Particles.Count;
foreach (Particle p in Particles)
{
p.X -= avgX;
p.Y -= avgY;
}
}
Это работает, и производительность не плохо, так как это O (п), но это «ошеломляюще параллельно». Посмотрите на мою реализацию PLINQ:
public void PNormalise()
{
double avgX = 0.0;
double avgY = 0.0;
Particles.AsParallel().ForAll(p =>
{
avgX += p.X;
avgY += p.Y;
});
avgX /= (double)Particles.Count;
avgY /= (double)Particles.Count;
Particles.AsParallel().ForAll(p =>
{
p.X -= avgX;
p.Y -= avgY;
});
}
Я не уверен, о работе, но я предположил бы, что это лучше. Проблема в том, что частицы все прыгают случайным образом. Я могу только предположить, что операции +=
на avgX
и avgY
конкурируют друг с другом, хотя они уже довольно атомные.
Есть ли что-нибудь, что я могу сделать, чтобы исправить это? Я не могу их lock
, потому что они не объекты, но я не уверен, что я бы хотел, так или иначе, потому что не блокировал довольно дорого?
Нет такой вещи, как «довольно атомный», операция либо атомарна, либо нет. – svick