2009-05-13 11 views
6

¿Alguien puede decirme cuál es el código correcto de Plinq para esto? Estoy sumando la raíz cuadrada del valor absoluto del seno de cada elemento para una matriz doble, pero el Plinq me está dando el resultado incorrecto.Plinq ofrece diferentes resultados de Linq: ¿qué estoy haciendo mal?

salida de este programa es:

LINQ agregada = 75,8310477905274 (correcto) PLINQ agregada = 38,0263653589291 (aproximadamente la mitad de lo que debería ser)

debo estar haciendo algo mal, pero no puedo trabajar en lo ...

(me estoy quedando esta con Visual Studio 2008 en un Core 2 Duo Windows 7 x64 PC.)

Aquí está el código:

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

Respuesta

3

El agregado funciona de forma ligeramente diferente en PLINQ.

De MSDN Blogs:

En lugar de esperar un valor de inicializar el acumulador, el usuario nos da una función fábrica que genera el valor:

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

Ahora , PLINQ puede inicializar un acumulador independiente para cada hilo. Ahora que cada hilo obtiene su propio acumulador , tanto la función de plegado como el acumulador que combina la función son libres de mutar los acumuladores . PLINQ garantiza que los acumuladores no serán accedidos al mismo tiempo desde múltiples subprocesos.

Así, en su caso, se debe también necesita para pasar una función de acumulador que suma las salidas de los agregados en paralelo (de ahí que estamos viendo un resultado que es aproximadamente la mitad de lo que debería ser).

0

Gracias MSDN Blogs. Ahora parece estar funcionando correctamente. Cambié mi código de la siguiente manera:

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