2

执行以下操作

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;
            }
        }
        );

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

4

1 回答 1

3

返回迭代值时,您应该聚合部分总和:

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()

于 2016-08-16T12:07:26.710 回答