Question

Quelqu'un peut-il me dire ce que le code PLINQ correct est pour cela? J'ajoute la racine carrée de la valeur absolue du sinus de chaque élément fo un double tableau, mais le PLINQ me donne un résultat erroné.

La sortie de ce programme est:

Linq total = 75,8310477905274 (correct) PLINQ total = 38,0263653589291 (environ la moitié de ce qu'il devrait être)

Je dois faire quelque chose de mal, mais je ne peux pas travailler ce ...

(je suis en cela avec Visual Studio 2008 sur un Core 2 Duo Windows 7 x64 PC.)

Voici le 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);
        }
    }
}
Était-ce utile?

La solution

Aggregate fonctionne un peu différemment dans PLINQ.

De MSDN Blogs:

  

Plutôt que d'attendre une valeur   initialiser l'accumulateur à la   l'utilisateur nous donne une fonction usine qui   génère la valeur:

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

Maintenant, PLINQ peut initialiser un   accumulateur indépendant pour chaque   fil. Maintenant que chaque thread obtient son   propre accumulateur, à la fois le pliage   la fonction et la combinaison de l'accumulateur   fonction sont libres de muter le   accumulateurs. PLINQ garantit que   accumulateurs ne sera pas accessible   simultanément à partir de plusieurs threads.

Alors, dans votre cas, vous devrez également passer une fonction d'accumulateur qui additionne les sorties des agrégats mis en parallèle (donc pourquoi vous voyez un résultat qui est à peu près la moitié de ce qu'elle devrait être).

Autres conseils

Merci blogs MSDN. Il semble maintenant fonctionner correctement. J'ai changé mon code comme suit:

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);
        }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top