Странно медленно: что случилось, когда TakeWhile встретил AsParallel?

Я знаю, что неправильное использование linq может привести к снижению производительности, но на этот раз это слишком странно.

Когда я вызываю "AsParallel.TakeWhile.AsParallel.ForAll", это НАМНОГО медленнее, чем "AsParallel.TakeWhile.ForAll". Может кто-нибудь объяснить, почему?

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 ответ

Решение

Когда вы вызываете AsParallel, среда начинает делить работу на более мелкие части, которые можно запланировать на разных ядрах. Эти части позже нужно было объединить обратно в результат. Это вызывает некоторые накладные расходы.

Вы уже сделали запрос параллельным с помощью первого "AsParallel", и когда вы вызываете его во второй раз, раздел происходит снова, вызывая еще больше накладных расходов, но не давая вам повышения производительности.

Посмотрите Понимание Ускорения в PLINQ для получения дополнительной информации.

Другие вопросы по тегам