我粗暴地强迫所有素数在2000000以下的总和。在那之后,为了好玩,我试图平行我的,但当我看到Parallel.For
给我不正确时,我有点惊讶总结!
这是我的代码:(C#)
static class Problem
{
public static long Solution()
{
long sum = 0;
//Correct result is 142913828922
//Parallel.For(2, 2000000, i =>
// {
// if (IsPrime(i)) sum += i;
// });
for (int i = 2; i < 2000000; i++)
{
if (IsPrime(i)) sum += i;
}
return sum;
}
private static bool IsPrime(int value)
{
for (int i = 2; i <= (int)Math.Sqrt(value); i++)
{
if (value % i == 0) return false;
}
return true;
}
}
我知道蛮力在这里是非常糟糕的解决方案,但这不是一个问题。我想我犯了一些非常愚蠢的错误,但我找不到它。因此,for
正在计算,但Parallel.For
不是。
答案 0 :(得分:4)
您正在从多个线程访问变量sum而不锁定它,因此读/写操作可能会重叠。
添加锁定会更正结果(但您将有效地序列化计算,失去您所瞄准的优势)。
您应该在每个线程上计算小计,并在末尾添加小计。有关详细信息,请参阅MSDN上的文章How to: Write a Parallel.For Loop That Has Thread-Local Variables。
long total = 0;
// Use type parameter to make subtotal a long, not an int
Parallel.For<long>(0, nums.Length, () => 0, (j, loop, subtotal) =>
{
subtotal += nums[j];
return subtotal;
},
(x) => Interlocked.Add(ref total, x)
);
答案 1 :(得分:0)
非常感谢大家的快速解答 我改变了
总和+ = i; 至 Interlocked.Add(ref sum,i);
现在效果很好。