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