gpt4 book ai didi

c# - Parallel.For() 与 Interlocked.CompareExchange() : poorer performance and slightly different results to serial version

转载 作者:太空宇宙 更新时间:2023-11-03 18:25:06 25 4
gpt4 key购买 nike

我尝试使用 Parallel.For() 计算列表的平均值。我决定反对它,因为它比简单的串行版本慢大约四倍。然而,令我感兴趣的是,它并没有产生与串行结果完全相同的结果,我认为了解原因会很有启发性。

我的代码是:

public static double Mean(this IList<double> list)
{
double sum = 0.0;


Parallel.For(0, list.Count, i => {
double initialSum;
double incrementedSum;
SpinWait spinWait = new SpinWait();

// Try incrementing the sum until the loop finds the initial sum unchanged so that it can safely replace it with the incremented one.
while (true) {
initialSum = sum;
incrementedSum = initialSum + list[i];
if (initialSum == Interlocked.CompareExchange(ref sum, incrementedSum, initialSum)) break;
spinWait.SpinOnce();
}
});

return sum / list.Count;
}

当我在 2000000 个点的随机序列上运行代码时,我得到的结果在最后 2 位数字与序列平均值不同。

我搜索了 stackoverflow 并找到了这个:VB.NET running sum in nested loop inside Parallel.for Synclock loses information .但是,我的情况与那里描述的情况不同。线程局部变量 temp 是不准确的原因,但我使用根据教科书 Interlocked.CompareExchange() 模式更新(我希望)的单个总和.由于性能不佳(这让我感到惊讶,但我知道开销),这个问题当然没有实际意义,但我很好奇是否可以从这个案例中学到一些东西。

感谢您的想法。

最佳答案

使用 double 是根本问题,您可以通过使用 long 来避免同步问题。你得到的结果实际上是正确的,但这永远不会让程序员高兴。

您发现 float 学是可以交流的,但是 not associative .或者换句话说,a + b == b + a 但是 a + b + c != a + c + b。在您的代码中暗示数字的添加顺序是非常随机的。

This C++ question也在谈论它。

关于c# - Parallel.For() 与 Interlocked.CompareExchange() : poorer performance and slightly different results to serial version,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36308056/

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