gpt4 book ai didi

c# - 使用 Parallel.For 在 C# 中锁定的意外行为

转载 作者:行者123 更新时间:2023-11-30 21:46:49 25 4
gpt4 key购买 nike

做以下事情

static object aggLock = new object();
static long max = 10000000;

static void Main(string[] args)
{
double totalSumSeq = 0;
double totalSumLock = 0;

// Seq
for (int i = 0; i < max; i++)
{
double y = Math.Sqrt(i);
totalSumSeq += y;
}

...
}

返回预期的 21,081,849,486.4393。

使用

        // Parallel.For(from, to, init, body, finally);
Parallel.For(0, max, () => 0.0, (i, pls, y) => // (LoopVariable, ParallelLoopState, ThreadLocalVariable)
{
y = Math.Sqrt(i);
return y;
},
partSum =>
{
lock (aggLock)
{
totalSumLock += partSum;
}
}
);

相反,我得到了完全不同的值,比如在竞争条件下。为什么?

最佳答案

返回迭代值时应聚合部分和:

Parallel.For(0, max, () => 0.0, (i, pls, y) => 
{
//y = Math.Sqrt(i);
int r = y + Math.Sqrt(i); // a + to fix it
return r;
}, ...

y 使用 () => 0.0 初始化为 0.0,并在分区末尾重新出现为 partSum。但是您只使用了分区的最后一个值。

使用 PLinq 的替代方案(但 Range() 不接受 long 最大值):

        double plinqSum = Enumerable
.Range(0, (int) max)
.AsParallel()
.Sum(i => Math.Sqrt(i)); // or just .Sum(Math.Sqrt);

这个 .AsParallel().Sum() 位本质上是您使用 Parallel.For()

构建的内容

关于c# - 使用 Parallel.For 在 C# 中锁定的意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38974325/

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