这是我第一次尝试并行代码,(第一次尝试工作正常并加速了一些代码)但是这下面引起了一些奇怪的问题,我不明白为什么。下面的两个for循环在大多数时间给出相同的结果但不是总是,即res!= res1。功能IdealGasEnthalpy只是计算一个数字,而不是改变其他任何东西,我无法弄清楚问题是什么,甚至在哪里开始看,有没有人提出任何建议?
double res = 0;
object lockObject = new object();
for (int I = 0; I < cc.Count; I++)
{
res += IdealGasEnthalpy(T, cc[I], enumMassOrMolar.Molar) * x[I];
}
double res1 = 0;
Parallel.For(0, cc.Count, I =>
{
res1 += IdealGasEnthalpy(T, cc[I], enumMassOrMolar.Molar) * x[I];
});
我尝试了以下代码,但与串行代码相比,它的速度非常慢,整个程序的执行时间加倍。
double res = 0.0d;
Parallel.For(0, cc.Count,
() => 0.0d,
(x, loopState, partialResult) =>
{
return partialResult += IdealGasEnthalpy(T, cc[x], enumMassOrMolar.Molar) * X[x];
},
(localPartialSum) =>
{
lock (lockObject)
{
res += localPartialSum;
}
});
还尝试了下面这个,因为并行版本的速度都慢了很多,所以这个例程会坚持非并行...
double res = 0.0d;
double[] partialresult = new double[cc.Count];
Parallel.For(0, cc.Count, i =>
{
partialresult[i] = IdealGasEnthalpy(T, cc[i], enumMassOrMolar.Molar) * X[i];
});
for (int i = 0; i < cc.Count; i++)
{
res += partialresult[i];
}*
答案 0 :(得分:1)
你的第二个操作需要进行互锁添加,因为+ =不是原子的。请记住,这是读取变量,添加变量和存储结果的简写。存在竞争条件,在存储新结果之前可能发生两次相同旧值的读取。您需要同步访问权限。
请注意,根据您的函数的计算成本如何,与Parallel.For
方法的联锁可能比仅执行串行方法更慢。归结为计算价值所花费的时间与同步和总结所花费的时间有关。
或者,您可以将结果存储在预先分配的数组中,然后在完成所有并行操作后进行求和。这样,没有两个操作修改同一个变量。由于您可以消除同步开销,因此该阵列可以交换内存以提高速度。