Transcript 11.PLINQ

Jarosław Kuchta
Programowanie Współbieżne
Równoległe kwerendy
danych
[email protected]
[email protected]
Podstawy

LINQ – Language-Integrated Query


język zapytań wbudowany w C# począwszy od
wersji 3.
PLINQ – Parallel LINQ

równoległa wersja LINQ
PLINQ
2
Przykład wyrażenia LINQ
// The Three Parts of a LINQ Query:
// 1. Data source.
int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 };
// 2. Query creation.// numQuery is an IEnumerable<int>
var numQuery =
from num in numbers
where (num % 2) == 0
select num;
// 3. Query execution.
foreach (int num in numQuery)
Console.Write("{0,1} ", num);
PLINQ
3
Źródła danych dla LINQ







tablice C#
łańcuchy znaków
kolekcje i listy .NET
bazy danych SQL
zbiory danych ADO.NET
dokumenty XML
…
PLINQ
4
Równoległa wersja wyrażenia
LINQ
// The Three Parts of a LINQ Query:
// 1. Data source.
int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 };
// 2. Query creation.// numQuery is an IEnumerable<int>
var numQuery =
from num in numbers.AsParallel()
where (num % 2) == 0
select num;
// 3. Query execution.
foreach (int num in numQuery)
Console.Write("{0,1} ", num);
PLINQ
5
foreach a ForAll
foreach (int num in numQuery)
aBag.Add(Compute(num)));
numQuery.ForAll
( (num) => aBag.Add(Compute(num)) );
PLINQ
6
Porównanie foreach i ForAll
PLINQ
7
Zalety i wady PLINQ

PLINQ dobrze się sprawdza, gdy:
elementy kolekcji są niezależne od siebie
 operacje łatwo dzielą się na niezależne wątki
 pojedyncza operacja jest "dość długotrwała"


Kosztem PLINQ jest narzut na:
podział danych ze źródła danych
 podział zadań na wątki
 zebranie danych z wątków
 scalenie wyników

PLINQ
8
Przykłady

Opłacalne:
var queryA = from num in numberList.AsParallel()
select ExpensiveFunction(num);

Nieopłacalne:
var queryB = from num in numberList.AsParallel()
where num % 2 > 0
select num;
PLINQ
9
Sekwencyjne wykonanie PLINQ


PLINQ próbuje wykonać kwerendę przynajmniej tak
samo szybko, jak LINQ.
Przełącza się na wykonanie sekwencyjne, gdy zawiera
klauzule:



Select, indeksowaną Where, indeksowaną SelectMany lub
ElementAt po zmianie kolejności lub filtrowaniu kolekcji
wejściowej,
Take, TakeWhile, Skip lub SkipWhile po zmianie kolejności
kolekcji wejściowej,
Concat, Reverse, Zip lub SequenceEquals, chyba że kolekcja
wejściowa jest oryginalnie indeksowana
PLINQ
10
Wymuszone wykonanie
równoległe
static void ForceParallel()
{
var customers = GetCustomers();
var parallelQuery = (from cust in customers.AsParallel()
.WithExecutionMode(ParallelExecutionMode.ForceParallelism)
where cust.City == "Berlin"
select cust.CustomerName)
.ToList();
}
PLINQ
11
Określenie liczby procesorów
var query = from item in source.AsParallel()
.WithDegreeOfParallelism(2)
where Compute(item) > 42
select item;
PLINQ
12
Kwerenda równoległa z
uporządkowaniem
var orderedCities = (from city in cities.AsParallel().AsOrdered()
where city.Population > 10000
select city)
.Take(1000);
PLINQ
13
Samodzielne partycjonowanie
danych
/ Static partitioning requires indexable source. Load balancing can use any IEnumerable.
var nums = Enumerable.Range(0, 100000000).ToArray();
// Create a load-balancing partitioner. Or specify false for static partitioning.
Partitioner<int> customPartitioner = Partitioner.Create(nums, true);
// The partitioner is the query's data source.
var q = from x in customPartitioner.AsParallel()
select x * Math.PI;
q.ForAll((x) =>
{
ProcessData(x);
});
PLINQ
14
Wizualizacja równoległości
PLINQ
15
Literatura

http://msdn.microsoft.com/enus/library/dd460688.aspx
PLINQ
16