Plinq给出了Linq不同的结果 - 我做错了什么?

时间:2009-05-13 10:02:18

标签: c# linq plinq

有人能告诉我Plinq的正确代码是什么吗?我将双数组中每个元素的正弦的绝对值的平方根加起来,但是Plinq给出了错误的结果。

该计划的输出是:

Linq aggregate = 75.8310477905274(正确) Plinq聚合= 38.0263653589291(大约应该是它的一半)

我一定做错了什么,但我找不到什么......

(我在Core 2 Duo Windows 7 x64 PC上运行Visual Studio 2008。)

以下是代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            double[] array = new double[100];

            for (int i = 0; i < array.Length; ++i)
            {
                array[i] = i;
            }

            double sum1 = array.Aggregate((total, current) => total + Math.Sqrt(Math.Abs(Math.Sin(current))));
            Console.WriteLine("Linq aggregate = " + sum1);

            IParallelEnumerable<double> parray = array.AsParallel<double>();
            double sum2 = parray.Aggregate((total, current) => total + Math.Sqrt(Math.Abs(Math.Sin(current))));
            Console.WriteLine("Plinq aggregate = " + sum2);
        }
    }
}

2 个答案:

答案 0 :(得分:3)

汇总在PLINQ中的工作方式略有不同。

来自MSDN Blogs:

  

而不是期望值   初始化累加器,   用户给我们一个工厂功能   生成值:

public static double Average(this IEnumerable<int> source)
{
    return source.AsParallel().Aggregate(
        () => new double[2],
        (acc, elem) => { acc[0] += elem; acc[1]++; return acc; },
        (acc1, acc2) => { acc1[0] += acc2[0]; acc1[1] += acc2[1]; return acc1; },
        acc => acc[0] / acc[1]);
}
  

现在,PLINQ可以初始化一个   每个独立的累加器   线。现在每个线程都得到了它   自己的累加器,都折叠   功能和累加器组合   函数可以自由改变   蓄电池。 PLINQ保证   不会访问累加器   同时来自多个线程。

因此,在您的情况下,您还需要传递一个累加器函数,该函数对并行聚合的输出求和(因此您看到的结果大约是它应该的一半)。

答案 1 :(得分:0)

谢谢你的MSDN博客。它现在似乎正常工作。我改变了我的代码如下:

using System;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            Test();
        }

        static void Test()
        {
            double[] array = new double[100];

            for (int i = 0; i < array.Length; ++i)
            {
                array[i] = i;
            }

            double sum1 = array.Aggregate((total, current) => total + Math.Sqrt(Math.Abs(Math.Sin(current))));
            Console.WriteLine("Linq aggregate = " + sum1);

            IParallelEnumerable<double> parray = array.AsParallel();

            double sum2 = parray.Aggregate
            (
                0.0,
                (total1, current1) => total1 + Math.Sqrt(Math.Abs(Math.Sin(current1))),
                (total2, current2) => total2 + current2,
                acc => acc
            );

            Console.WriteLine("Plinq aggregate = " + sum2);
        }
    }
}