2009-05-13 4 views
6

誰でも正しいPlinqコードを教えていただけますか?私はダブル配列の各要素の正弦の絶対値の平方根を足していますが、Plinqは私に間違った結果を与えています。このプログラムからPlinqはLinqとは異なる結果を出します - どうしたのですか?

出力は次のとおりです。

のLINQ集計= 75.8310477905274(正しい) PLINQの集計= 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); 
     } 
    } 
} 

答えて

3

集計はPLINQでは若干異なります。今

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

MSDN Blogs:

よりもむしろ に値を期待から

がにアキュムレータを初期化し、 ユーザーは、私たちに が値を生成するファクトリ関数を提供します、PLINQはごとに 独立アキュムレータを初期化できますスレッド。各スレッドが自身のアキュムレータ を取得したので、 フォールディングファンクションと ファンクションを組み合わせたアキュムレータは、 アキュムレータを自由に変更することができます。 PLINQは、 アキュムレータが複数のスレッドから同時に にアクセスされないことを保証します。

したがって、あなたの場合、並列化された集約の出力を合計するアキュムレータ関数を渡す必要があります(なぜ、結果がおよそ半分であるのかわかりません)。

0

ありがとうございました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); 
     } 
    } 
} 
関連する問題