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

发布于 2024-07-20 04:35:59 字数 1148 浏览 7 评论 0原文

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

该程序的输出为:

Linq 聚合 = 75.8310477905274 (正确) Plinqaggregate = 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);
        }
    }
}

Can anyone tell me what the correct Plinq code is for this? I'm adding up the square root of the absolute value of the sine of each element fo a double array, but the Plinq is giving me the wrong result.

Output from this program is:

Linq aggregate = 75.8310477905274 (correct)
Plinq aggregate = 38.0263653589291 (about half what it should be)

I must be doing something wrong, but I can't work out what...

(I'm running this with Visual Studio 2008 on a Core 2 Duo Windows 7 x64 PC.)

Here's the code:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

七月上 2024-07-27 04:36:00

PLINQ 中聚合的工作方式略有不同。

来自 MSDN 博客:

而不是期望一个值
将累加器初始化为
用户给我们一个工厂函数
生成值:

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 保证
累加器将不会被访问
多个线程并发。

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

Aggregate works slightly differently in PLINQ.

From MSDN Blogs:

Rather than expecting a value to
initialize the accumulator to, the
user gives us a factory function that
generates the value:

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

Now, PLINQ can initialize an
independent accumulator for each
thread. Now that each thread gets its
own accumulator, both the folding
function and the accumulator combining
function are free to mutate the
accumulators. PLINQ guarantees that
accumulators will not be accessed
concurrently from multiple threads .

So, in your case, you would also need to pass an accumulator function which sums the outputs of the paralleled aggregates (hence why you're seeing a result that is roughly half of what it should be).

烟沫凡尘 2024-07-27 04:36:00

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

Thank you MSDN Blogs. It now seems to be working correctly. I changed my code as follows:

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);
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文