0

今日は、LinqクエリとPLinqクエリのパフォーマンスへの影響をテストしました。したがって、msdnの方法に関する記事を使用しました:PLINQクエリのパフォーマンスを測定します。

void Main()
{
        var source = Enumerable.Range(0, 600000000);
        System.Diagnostics.Stopwatch sw;    

        var queryToMeasure1 = from num in source
                             where num % 3 == 0
                             select Math.Sqrt(num);

        var queryToMeasure2 = from num in source.AsParallel()
                             where num % 3 == 0
                             select Math.Sqrt(num);                          

        long freq = Stopwatch.Frequency;
        Console.WriteLine("Timer frequency in ticks per second = {0}", freq);

        Console.WriteLine("Measuring 1");
        sw = System.Diagnostics.Stopwatch.StartNew();   
        foreach (var n in queryToMeasure1) { }  
        Console.WriteLine("Total ticks: {0} - Elapsed time: {1} ms", sw.ElapsedTicks, sw.ElapsedMilliseconds);      

        Console.WriteLine("Measuring 2");
        sw = System.Diagnostics.Stopwatch.StartNew();   
        foreach (var n in queryToMeasure2) { }  
        Console.WriteLine("Total ticks: {0} - Elapsed time: {1} ms", sw.ElapsedTicks, sw.ElapsedMilliseconds);

        Console.WriteLine("Measuring 3");
        sw = System.Diagnostics.Stopwatch.StartNew();           
        System.Threading.Tasks.Parallel.ForEach(queryToMeasure1, n => {});          
        Console.WriteLine("Total ticks: {0} - Elapsed time: {1} ms", sw.ElapsedTicks, sw.ElapsedMilliseconds);

        Console.WriteLine("Measuring 4");
        sw = System.Diagnostics.Stopwatch.StartNew();           
        System.Threading.Tasks.Parallel.ForEach(queryToMeasure2, n => {});      
        Console.WriteLine("Total ticks: {0} - Elapsed time: {1} ms", sw.ElapsedTicks, sw.ElapsedMilliseconds);

        Console.WriteLine("Measuring 5");
        sw = System.Diagnostics.Stopwatch.StartNew();   
        queryToMeasure2.ForAll(n => {});    
        Console.WriteLine("Total ticks: {0} - Elapsed time: {1} ms", sw.ElapsedTicks, sw.ElapsedMilliseconds););
}

テスト環境:Win7 Enterprise上のLinqPad4、64ビット、8 GB RAM、I7-2600(8コア)

1つのコア(測定1)でのクエリが、並列クエリよりも高速である理由を理解しましたが、説明できません。並列タスクのメリットを享受するには、選択したデリゲートをさらに追加する必要がありますか?

しかし今、結果は:

1.実行:60000の列挙可能な範囲で:

Timer frequency in ticks per second = 3312851
Measuring 1
Total ticks: 3525 - Elapsed time: 1 ms
Measuring 2
Total ticks: 15802 - Elapsed time: 4 ms
Measuring 3
Total ticks: 5940 - Elapsed time: 1 ms
Measuring 4
Total ticks: 26862 - Elapsed time: 8 ms
Measuring 5
Total ticks: 4387 - Elapsed time: 1 ms

2.実行:600000000の列挙可能な範囲で:

Timer frequency in ticks per second = 3312851
Measuring 1
Total ticks: 29740243 - Elapsed time: 8977 ms
Measuring 2
Total ticks: 33722438 - Elapsed time: 10179 ms
Measuring 3
Total ticks: 77145502 - Elapsed time: 23286 ms
Measuring 4
Total ticks: 120078284 - Elapsed time: 36246 ms
Measuring 5
Total ticks: 30899585 - Elapsed time: 9327 ms

興味深い事実:テストスクリプトを実行する前にガベージコレクターを使用すると、測定4の時間が大幅に増加します。

3.実行:600000000の列挙可能な範囲とガベージコレクター(LinqPadから):

Timer frequency in ticks per second = 3312851
Measuring 1
Total ticks: 29597830 - Elapsed time: 8934 ms
Measuring 2
Total ticks: 33532083 - Elapsed time: 10121 ms
Measuring 3
Total ticks: 76403692 - Elapsed time: 23062 ms
Measuring 4
Total ticks: 58534548 - Elapsed time: 17668 ms
Measuring 5
Total ticks: 32943622 - Elapsed time: 9944 ms

結論として、方法1は、選択デリゲートが増えるときに、小さな選択クエリと方法5を実行するのに最も適したオプションであると言えますか?

4

1 に答える 1

1

あなたの計算は非常に安いです。デリゲート呼び出しは計算自体よりもコストがかかる可能性があるため、これらは非並列 LINQ の良い候補とは言えません。PLINQ には、タスクの開始、スレッド間でのデータの同期とコピーなど、多くの追加のオーバーヘッドがあります。これを試して:

bool Where(int i) {
 var sum = 0; 
 for (10000 times) {
  sum += i;
 }
 return i % 3 == 0;
}

その関数を where 句で使用します。この関数は非常にコストがかかるため、スレッド化と同期によるオーバーヘッドが実行時間を支配することはなくなります。

したがって、基本的には、PLINQ の最悪のケースのユース ケースを測定しています。興味深いものを測定してみてください。

于 2012-08-24T10:36:35.283 に答える