Управление параллелизмом
71LINQ --- PLINQ --- Управление параллелизмом
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);
Ограничение степени параллелизма
Можно потребовать, чтобы 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. Это может быть удобно, если необходимо ограничить влияние запроса на машину, которая должна выполнять и другие задачи.