Управление параллелизмом

71

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

Принудительное параллельное выполнение

В некоторых случаях PLINQ может решить, что запрос лучше выполнять последовательно. Этим можно управлять за счет применения расширяющего метода WithExecutionMode к типу ParallelQuery. Метод WithExecutionMode принимает значение из перечисления ParallelExecutionMode. Этих значений два: Default (режим по умолчанию, который позволяет PLINQ решать, как выполнять обработку) и ForceParallelism (использовать PLINQ даже если накладные расходы, связанные с параллельным выполнением, превосходят выигрыш от него). Ниже показано, как вызвать принудительно параллельное выполнение:

string[] cars = { "Nissan", "Aston Martin", "Chevrolet", "Alfa Romeo", "Chrysler", "Dodge", "BMW",
                              "Ferrari", "Audi", "Bentley", "Ford", "Lexus", "Mercedes", "Toyota", "Volvo", "Subaru", "Жигули :)"};

            // Запрос Parallel LINQ
            IEnumerable<string> auto = cars
                .AsParallel()
                .WithExecutionMode(ParallelExecutionMode.ForceParallelism)
                .Where(p => p.Contains("a"))
                .Select(p => p);

            foreach (string s in auto)
                Console.WriteLine(s);
Принудительное параллельное выполнение с использованием метода WithExecutionMode

Ограничение степени параллелизма

Можно потребовать, чтобы PLINQ ограничивал количество разделов, обрабатываемых параллельно, с использованием расширяющего метода WithDegreeOfParallelism, который работает с типом ParallelQuery. Этот метод принимает аргумент int, который устанавливает максимальное количество разделов, которые должны быть обработаны одновременно; это называется степенью параллелизма.

Установка степени параллелизма не принуждает PLINQ использовать именно столько разделов, а лишь указывает верхний предел. PLINQ может решить использовать меньшее количество разделов, чем указано, или же, если метод WithExecutionMode не использовался, может вообще выполнять запрос последовательно. Применение этого метода продемонстрировано ниже:

...
// Запрос Parallel LINQ
            IEnumerable<string> auto = cars
                .AsParallel()
                .WithExecutionMode(ParallelExecutionMode.ForceParallelism)
                .WithDegreeOfParallelism(2)
                .Where(p => p.Contains("a"))
                .Select(p => p);

В коде задана максимальная степень параллелизма 2, а это означает, что обрабатывать одновременно понадобится максимум два раздела. Т.е. компьютер будет использовать не более 2 ядер для обработки запроса PLINQ. Это может быть удобно, если необходимо ограничить влияние запроса на машину, которая должна выполнять и другие задачи.

Лучший чат для C# программистов