"...Изучение и анализ примеров.
В и приведены описания и приложены исходные коды параллельных программ..." Непонятно что такое - "В и приведены описания" и где именно приведены и приложены исходные коды. |
Введение в PLINQ
PLINQ (Parallel Language-Integrated Query) - параллельный интегрированный язык запросов - является параллельной реализацией LINQ. Отличие PLINQ от LINQ состоит в том, что запросы выполняются параллельно, используя, обычно, все доступные ядра/процессоры.
7.1 Использование PLINQ
PLINQ предназначен для параллельного выполнения LINQ-запросов и потому его реализация встроена в библиотеку System.Linq. PLINQ полностью поддерживает все операторы запросов, имеющиеся в .NET, и имеет минимальное влияние на существующую модель использования и исполнения LINQ-операторов.
Рассмотрим простой пример использования LINQ. Предположим, что мы имеем метод, который проверяет делимость целого числа на 5. Добавим в него некоторую длительную обработку, чтобы этот метод можно было использовать в параллельных программах:
private static bool IsDivisibleBy5 ( int p ) { // Моделирование длительной обработки for ( int i = 0; i < 10000000; i++ ) { i++; i--; } return p % 5 == 0; }Пример 7.1.
Следующий фрагмент программы с использование LINQ-операторов позволяет подсчитать количество чисел в интервале от 1 до 1000, которые делятся на 5:
IEnumerable<int> arr = Enumerable.Range ( 1, 1000 ); var q = from n in arr where ISDivisibleBy5 ( n ) select n; List<int> list = q.ToList(); Console.WriteLine ( list.Count.ToString() );Пример 7.2.
Чтобы распараллелить этот запрос средствами PLINQ, достаточно применить к источнику данных (в данном случае, это перечислимый массив arr) extension-метод AsParallel():
IEnumerable<int> arr = Enumerable.Range ( 1, 1000 ); var q = from n in arr.AsParallel() where ISDivisibleBy5 ( n ) select n; List<int> list = q.ToList(); Console.WriteLine ( list.Count.ToString() );Пример 7.3.
В действительности, LINQ-запросы, записанные в SQL-подобном синтаксисе, как в Примере 2, переводятся в серию вызовов extension-методов классов, содержащихся в System.Linq.Enumerable. Другими словами, запрос из Примера 2 может быть переписан в следующей эквивалентной форме:
IEnumerable<int> q = Enumerable.Select<int,int> ( Enumerable.Where<int> ( arr, delegate (int n) { return IsDivisibleBy5 (n); } ), delegate (int n) { return n; } );Пример 7.4.
Наряду с Enumerable, библиотека System.Linq содержит эквивалентный класс ParallelEnumerable, который содержит тот же набор методов, что и класс Enumerable, но предназначенных для параллельного исполнения.
Тогда параллельная реализация Примера 4 запишется следующим образом:
IParallelEnumerable<int> q = ParallelEnumerable.Select<int,int> ( ParallelEnumerable.Where<int> ( ParallelQuery.AsParallel<int> (arr), delegate (int n) { return IsDivisibleBy5 (n); } ), delegate (int n) { return n; } );Пример 7.5.
Рассмотрим еще один (схематичный) запрос, записанный в синтаксисе LINQ:
IEnumerable<T> data = …; var q = from x in data where p ( x ) orderby k ( x ) select f ( x ); foreach ( var e in q ) a ( e );Пример 7.6.
Распараллеливание исполнения этого запроса снова достигается применением extension-метода AsParallel():
IEnumerable<T> data = …; var q = from x in data.AsParallel() where p ( x ) orderby k ( x ) select f ( x ); foreach ( var e in q ) a ( e );Пример 7.7.
И снова запрос из Примера 6 может быть эквивалентно переписан с использованием Enumerable:
IEnumerable<T> data = …; var q = Enumerable.Select( Enumerable.OrderBy( Enumerable.Where(data, x => p(x)), x => k(x)), x => f(x)); foreach (var e in q) a(e);Пример 7.8.
Распараллелить запрос из Примера 8 легко:
IEnumerable<T> data = …; var q = ParallelEnumerable.Select( ParallelEnumerable.OrderBy( ParallelEnumerable.Where(data.AsParallel(), x => p(x)), x => k(x)), x => f(x)); foreach (var e in q) a(e);Пример 7.9.
Запрос из Примера 8 можно переписать еще одним эквивалентным способом, который отличается тем, что в нем опущены явные указания типа Enumerable, что сокращает запрос в записи, но вызывает процедуру (неявного) вывода типов на этапе компиляции программы:
IEnumerable<T> data = …; var q = data.Where(x => p(x)).Orderby(x => k(x)).Select(x => f(x)); foreach (var e in q) a(e);Пример 7.10.
Распараллеливание запроса из Примера 10 снова происходит применением метода AsParallel() к источнику данных:
IEnumerable<T> data = …; var q = data.AsParallel(). Where(x => p(x)).Orderby(x => k(x)).Select(x => f(x)); foreach (var e in q) a(e);Пример 7.11.