Распараллеливание запроса методом AsParallel()
Едва ли не самым удобным средством PLINQ является возможность просто создавать параллельный запрос. Нужно лишь вызвать метод AsParallel() для источника данных. Метод AsParallel() определен в классе ParallelEnumerable и возвращает источник данных, инкапсулированный в экземпляре объекта типа ParallelQuery. Это дает возможность поддерживать методы расширения параллельных запросов. После вызова данного метода запрос разделяет источник данных на части и оперирует с каждой из них таким образом, чтобы извлечь максимальную выгоду из распараллеливания. (Если распараллеливание оказывается невозможным или неприемлемым, то запрос, как обычно, выполняется последовательно.) Таким образом, добавления в исходный код единственного вызова метода AsParallel() оказывается достаточно для того, чтобы превратить последовательный запрос LINQ в параллельный запрос LINQ. Для простых запросов это единственное необходимое условие.
Существуют как обобщенные, так и необобщенные формы метода AsParallel(). Ниже приведена простейшая обобщенная его форма:
Public static ParallelQuery AsParallel(this IEnumerable source)
public static ParallelQuery<TSource>
AsParallel<TSource>(this IEnumerable<TSource> source)
где TSource обозначает тип элементов в последовательном источнике данных source.
Ниже приведен пример, демонстрирующий простой запрос PLINQ.
// Простой запрос PLINQ.
using System;
using System.Linq;
class PLINQDemo {
static void Main() {
int[] data = new int[10000000];
Инициализировать массив данных положительными значениями,
|
|
for(int i=0; i < data.Length; i++) data[i] = i;
А теперь ввести в массив данных ряд отрицательных значений
data[1000] = -1;
data[14000] = -2;
data[15000] = -3;
data[676000] = -4;
data[8024540] = -5;
data[9908000] = -6;
Использовать запрос PLINQ для поиска отрицательных значений,
var negatives = from val in data.AsParallel() where val < 0 select val;
Foreach(var v in negatives)
Console.Write(v + " ");
Console.WriteLine();
}
}
Эта программа начинается с создания крупного массива data, инициализируемого целыми положительными значениями. Затем в него вводится ряд отрицательных значений. А далее формируется запрос на возврат последовательности отрицательных значений. Ниже приведен этот запрос.
var negatives = from val in data.AsParallel() where val < 0 select val;
В этом запросе метод AsParallel() вызывается для источника данных, в качестве которого служит массив data. Благодаря этому разрешается параллельное выполнение операций над массивом data, а именно: поиск отрицательных значений параллельно в нескольких потоках. По мере обнаружения отрицательных значений они добавляются в последовательность вывода. Это означает, что порядок формирования последовательности вывода может и не отражать порядок расположения отрицательных значений в массиве data. В качестве примера ниже приведен результат выполнения приведенного выше кода в двухъядерной системе.
|
|
-5 -6 -1 -2 -3 -4
Как видите, в том потоке, где поиск выполнялся в верхней части массива, отрицательные значения -5 и -6 были обнаружены раньше, чем значение -1 в том потоке, где поиск происходил в нижней части массива. Следует, однако, иметь в виду, что из-за отличий в степени загрузки задачами, количества доступных процессоров и прочих факторов системного характера могут быть получены разные результаты. А самое главное, что результирующая последовательность совсем не обязательно будет отражать порядок формирования исходной последовательности.
Применение метода AsOrdered()
Как отмечалось в предыдущем разделе, по умолчанию порядок формирования результирующей последовательности в параллельном запросе совсем не обязательно должен отражать порядок формирования исходной последовательности. Более того, результирующую последовательность следует рассматривать как практически неупорядоченную. Если же результат должен отражать порядок организации источника данных, то его нужно запросить специально с помощью метода AsOrdered(), определенного в классе ParallelEnumerable. Ниже приведены обобщенная и необобщенная формы этого метода:
Дата добавления: 2019-02-12; просмотров: 264; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!