2009-05-13 2 views
6

Может ли кто-нибудь сказать мне, какой именно код Плинка для этого? Я добавляю квадратный корень из абсолютного значения синуса каждого элемента для двойного массива, но Плинк дает мне неправильный результат.Плинк дает разные результаты от Линка - что я делаю неправильно?

Выход из этой программы:

Linq агрегат = +75,8310477905274 (правильный) PLINQ агрегат = 38,0263653589291 (примерно вдвое меньше, чем должно быть)

я должен делать что-то неправильно, но я не могу выяснить, что ...

(Я бегу это с Visual Studio 2008 на Core 2 Duo Windows 7 x64 ПК.)

Вот код:

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

ответ

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 гарантирует, что аккумуляторы не будут доступны одновременно из нескольких потоков.

Таким образом, в вашем случае, вы также должны пройти агрегатную функцию, которая суммирует выходы параллельно подключенных агрегатов (следовательно, почему вы видите результат, который примерно вдвое меньше, чем должно быть).

0

Спасибо, MSDN Blogs. Теперь он работает правильно. Я изменил свой код следующим образом:

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); 
     } 
    } 
} 
Смежные вопросы