PLINQ يعطي نتائج مختلفة من ينق - ماذا أفعل الخطأ؟

StackOverflow https://stackoverflow.com/questions/857107

  •  21-08-2019
  •  | 
  •  

سؤال

ويمكن لأحد أن يقول لي ما هو رمز PLINQ الصحيح لهذا؟ أنا بجمع الجذر التربيعي للقيمة المطلقة للجيب كل عنصر FO مجموعة مزدوجة، ولكن PLINQ هو إعطائي نتيجة خاطئة.

والناتج من هذا البرنامج هو:

وينق الكلي = 75،8310477905274 (الصحيح) PLINQ الكلي = 38،0263653589291 (حوالي نصف ما ينبغي أن يكون)

لا بد لي من أن تفعل شيئا خاطئا، ولكن لا أستطيع أن أعمل ما ...

و(أنا على التوالي هذا مع Visual Studio 2008 على كور 2 ديو ويندوز 7 إلى x64 PC).

وهنا رمز:

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);
        }
    }
}
هل كانت مفيدة؟

المحلول

والحصى يعمل بشكل مختلف قليلا في 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 أن   لن يتم الوصول إليها بطاريات   في وقت واحد من المواضيع متعددة.

وهكذا، في الحالة الخاصة بك، سوف تحتاج أيضا لتمرير وظيفة اللاسلكي الذي يلخص مخرجات المجاميع يتوازى (وبالتالي لماذا ترونه نتيجة لذلك وهذا هو تقريبا نصف ما يجب أن يكون).

نصائح أخرى

وشكرا 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);
        }
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top