奇怪的慢:当TakeWhile遇到AsParallel时发生了什么?

时间:2014-06-20 08:04:51

标签: c# linq plinq

我知道linq的错误使用可能会导致性能下降,但这一次太奇怪了。

当我调用“AsParallel.TakeWhile.AsParallel.ForAll”时,它比“AsParallel.TakeWhile.ForAll”慢 MUCH 。有人能解释一下原因吗?

using System;
using System.Diagnostics;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Action<int> doNothing = i => { };

            var stopwatch = Stopwatch.StartNew();
            Enumerable.Range(1, 100).AsParallel().TakeWhile(m => m < 10)
                .ForAll(doNothing);
            var ticks1 = stopwatch.ElapsedTicks;

            stopwatch.Restart();
            Enumerable.Range(1, 100).AsParallel().TakeWhile(m => m < 10)
                .AsParallel() // spend much more time with this AsParallel 
                .ForAll(doNothing);
            var ticks2 = stopwatch.ElapsedTicks;

            Console.WriteLine("ticks without AsParallel: {0}\r\n with AsParallel: {1}", ticks1, ticks2);
            //ticks without AsParallel: 87956
            //with AsParallel: 6688708
            Console.Read();
        }
    }
}

1 个答案:

答案 0 :(得分:6)

当您调用AsParallel时,框架开始将工作分成更小的部分,这些部分可以在不同的核心上进行调度。这些部分后来需要合并回结果。这会导致一些开销。

您已经通过第一个“AsParallel”使查询并行,当您再次调用它时,分区再次发生,导致更多开销,但不会提升性能。

有关详细信息,请参阅Understanding Speedup in PLINQ