.Net Parallel.For奇怪的行为

时间:2010-07-31 12:07:34

标签: .net-4.0

我粗暴地强迫所有素数在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不是。

2 个答案:

答案 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);

现在效果很好。