Поделиться через


Параметры слияние в PLINQ

Если запрос выполняется как параллельный, PLINQ разделяет исходную последовательность, чтобы несколько потоков могли работать с различными частями параллельно, обычно в отдельных потоках. Если результаты необходимо получить в одном потоке, например в цикле foreach (For Each в Visual Basic), результаты из каждого потока должны быть объединены в одну последовательность. Тип слияния, выполняемого PLINQ, зависит от операторов, которые присутствуют в запросе. Например, операторы, указывающие новую последовательность результатов, должны помещать в буфер все элементы из всех потоков. Для потока-потребителя (который также является потоком пользователя приложения) полностью буферизованный запрос может выполняться в течение значительного периода времени до момента создания первого результата. Другие операторы по умолчанию являются частично буферизованными. Они выдают результаты в пакетах. Один оператор, ForAll<TSource>, не буферизован по умолчанию. Он выдает все элементы из всех потоков немедленно.

С помощью метода WithMergeOptions<TSource>, как показано в следующем примере, можно предоставить подсказку PLINQ, указывающую тип выполняемого слияния.

        Dim scanlines = From n In nums.AsParallel().WithMergeOptions(ParallelMergeOptions.NotBuffered)
                        Where n Mod 2 = 0
                        Select ExpensiveFunc(n)

var scanLines = from n in nums.AsParallel()
                    .WithMergeOptions(ParallelMergeOptions.NotBuffered)
                where n % 2 == 0
                select ExpensiveFunc(n);

Полный пример см. в разделе Практическое руководство. Задание параметров слияния в PLINQ.

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

ParallelMergeOptions

Перечисление ParallelMergeOptions включает следующие параметры, указывающие поддерживаемым формам запроса, как выдаются конечные результаты запроса, если они используются в одном потоке.

  • Not Buffered

    Параметр NotBuffered приводит к возврату каждого обработанного элемента из каждого потока сразу после его создания. Такое поведение аналогично потоковой передаче выходных данных. При наличии в запросе оператора AsOrdered() параметр NotBuffered сохраняет порядок исходных элементов. Несмотря на то что параметр NotBuffered начинается возвращать результаты, как только они становятся доступными, общее время для получения всех результатов может по-прежнему быть больше по сравнению с использованием других параметров слияния.

  • Auto Buffered

    При использовании параметра AutoBuffered запрос собирает элементы в буфер и затем периодически выдает все содержимое буфера сразу в поток-потребитель. Это аналогично выдаче исходных данных в блоках вместо использования поведения потоковой передачи NotBuffered. Параметру AutoBuffered может потребоваться больше времени, чем параметру NotBuffered, чтобы сделать первый элемент доступным в потоке-потребителе. Размер буфера и точное поведение выдачи не настраиваются и могут различаться в зависимости от различных факторов, относящихся к запросу.

  • FullyBuffered

    При выборе параметра FullyBuffered выходные данные всего запроса буферизуются до выдачи какого-либо элемента. При использовании этого параметра может потребоваться больше времени для того, чтобы сделать первый элемент доступным в потоке-потребителе, но полные результаты по-прежнему могут производиться быстрее по сравнению с использованием других параметров.

Операторы запроса, поддерживающие параметры слияния

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

Оператор

Ограничения

AsEnumerable<TSource>

Нет.

Cast<TResult>

Нет.

Concat

Неупорядоченные запросы, содержащие только массив или источник списка.

DefaultIfEmpty

Нет.

OfType<TResult>

Нет.

Reverse<TSource>

Неупорядоченные запросы, содержащие только массив или источник списка.

Select

Нет.

SelectMany

Нет.

Skip<TSource>

Нет.

Take<TSource>

Нет.

Where

Нет.

Все другие операторы запроса PLINQ могут игнорировать параметры слияния, предоставленные пользователем. Некоторые операторы запроса, например Reverse<TSource> и OrderBy, не могут выдавать какие-либо элементы, пока не будут созданы и переупорядочены все элементы. Таким образом, при использовании ParallelMergeOptions в запросе, в котором также содержится оператор, например Reverse<TSource>, поведение слияния не будет применяться в запросе, пока этот оператор не создаст все результаты.

Возможность некоторых операторов обрабатывать параметры слияния зависит от типа исходной последовательности и от того, использовался ли оператор AsOrdered ранее в запросе. Метод ForAll<TSource> всегда является NotBuffered, он выдает элементы немедленно. Метод OrderBy всегда является FullyBuffered, он должен сортировать весь список перед выдачей.

См. также

Задачи

Практическое руководство. Задание параметров слияния в PLINQ

Основные понятия

Parallel LINQ (PLINQ)