Томский политехнический университет
Опубликован: 23.01.2013 | Доступ: свободный | Студентов: 1158 / 192 | Длительность: 12:09:00
Лекция 9:

PLINQ Операторы и методы

Аннотация: В рамках данной лекции будут рассмотрены следующие вопросы: перечесление ParallelExecutionMode; метод WithDegreeOfParallelism; метод AsOrdered; метод Range; метод Repeat; метод AsUnordered; метод AsSequential; метод WithMergeOptions; метод ForAll.

Перечесление ParallelExecutionMode

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

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

Пример использования метода WithExecutionMode() продемонстрирован ниже:

int[] numbers = { 1, 2, 3, 7, 3, 8, 3, 55, 7, 9, 33, 45, 5, 68, 4, 34, 3, 1, 34, 63, 2, 54, 7, 4, 32, 7, 4, 3, 6, 87, 23 };
      var num = from i in numbers.AsParallel()
                   .WithExecutionMode(ParallelExecutionMode.ForceParallelism)
                      where i > 5 
                      select i;
    foreach (var s in num)
            {
                Console.WriteLine(s);
            }
            Console.ReadLine();
Результат выполнения PLINQ-запроса с использованием метода WithExecutionMode()

увеличить изображение
Рис. 12.1. Результат выполнения PLINQ-запроса с использованием метода WithExecutionMode()

Метод WithDegreeOfParallelism

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

int[] numbers = { 1, 2, 3, 7, 3, 8, 3, 55, 7, 9, 33, 45, 5, 68, 4, 34, 3, 1, 34, 63, 2, 54, 7, 4, 32, 7, 4, 3, 6, 87, 23 };
            var num = from i in numbers.AsParallel()
                   .WithExecutionMode(ParallelExecutionMode.ForceParallelism)
.WithDegreeOfParallelism(1)
                      where i > 5 
                      select i;
            foreach (var s in num)
            {
                Console.WriteLine(s);
            }
            Console.ReadLine();
 Результат выполнения PLINQ-запроса с использованием метода WithDegreeOfParallelism()

увеличить изображение
Рис. 12.2. Результат выполнения PLINQ-запроса с использованием метода WithDegreeOfParallelism()

В данном примере степень параллелизма равен 1, что означает что программа будет использовать не более одного процесса (ядра) и выполнит PLINQ запрос в 1 поток т.е последовательно. Использование данного метода может быть удобно, если необходимо ограничить влияние запроса на машину, которая должна выполнять и другие задачи.

Метод AsOrdered

Одним из недостатков параллельного выполнения запросов PLINQ является то, что при объединении результатов, нарушается порядок. Если необходимо сохранить порядок элементов, то используется метод AsOrdered(). Использование метода AsOrdered() для последовательностей большого размера снижает производительность, поскольку в этом случае необходимо отслеживать исходную позицию элементов. Данный метод содержит два типа перегрузки, которые представлены ниже:

  • Первый тип перегрузки метода AsOrdered() принудительно устанавливает порядок результатов для ParallelQuery <TSource>. Результатом операции также является объект ParallelQuery <TSource>, который можно использовать как входную последовательность для запроса PLINQ:
    public static ParallelQuery<TSource> AsOrdered<TSource>(
    this ParallelQuery<TSource> source
    )

    где Tsource - тип элементов последовательности source; source - входная последовательность.

  • Второй тип перегрузки метода AsOrdered() использует слаботипизированый ParallelQuery:
    public static ParallelQuery AsOrdered(
    	this ParallelQuery source
    )

    где source - входная последовательность.

Ниже продемонстрирован пример кода, в котором используется метод AsOrdered():

int[] numbers = { 1, 2, 3, 7, 3, 8, 3, 55, 7, 9, 33, 45, 5, 68, 4, 34, 3, 1, 34, 63, 2, 54, 7, 4, 32, 7, 4, 3, 6, 87, 23 };
            var num = from i in numbers.AsParallel()
                  .AsOrdered()
                      where i > 5 
                      select i;
            foreach (var s in num)
            {
                Console.WriteLine(s);
            }
Console.ReadLine();

Запуск кода дает показанные ниже результаты. Здесь видно, что порядок исходной последовательности предохранен:

 Результат выполнения PLINQ-запроса с использованием метода AsOrdered()

увеличить изображение
Рис. 12.3. Результат выполнения PLINQ-запроса с использованием метода AsOrdered()

Метод Range

Метод Range() - генерирует последовательность целых чисел в заданном диапазоне. Данный метод имеет следующий синтаксис при объявлении:

public static ParallelQuery<int> Range( 
         int start, int count)

где start - это значение первого целого числа для последовательности; count - количество генерируемых последовательных целых чисел.

Ниже приведен пример использования метода Range():

var numbers = ParallelEnumerable.Range(1, 100);
       var num = from i in numbers.AsOrdered()
                      where i >= 50
                      select i;
            foreach (var s in num)
            {
                Console.WriteLine(s);
            }
             Console.ReadLine();

В данном примере вызывается метод Range() для создания ParallelQuery<int>, содержащего диапазон целых чисел от 1 до 100 включительно. Данная последовательность служит основой для LINQ - запроса в дальнейшем.

 Результат выполнения PLINQ-запроса с использованием метода Range()

увеличить изображение
Рис. 12.4. Результат выполнения PLINQ-запроса с использованием метода Range()
Владимир Каширин
Владимир Каширин

Вопрос по Курсу: "Параллельное программирование с использованием MS VisualStudia 2010".

При компиляции Самостоятельного задания (одновременная отрисовка прямоугольников, эллипсов и выдача в текст-бокс случайного числа) среда предупреждает: suspend - устаревшая команда; примените monitor, mutex и т.п.

Создаётся впечатление, что Задание создано в более поздней среде, чем VS 2010.