160 likes | 310 Views
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:
E N D
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 PLINQ
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
Ź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
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
foreach a ForAll foreach (int num in numQuery) aBag.Add(Compute(num))); numQuery.ForAll ( (num) => aBag.Add(Compute(num)) ); PLINQ
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
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
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
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
Określenie liczby procesorów var query = from item in source.AsParallel() .WithDegreeOfParallelism(2) where Compute(item) > 42 select item; PLINQ
Kwerenda równoległa z uporządkowaniem var orderedCities = (from city in cities.AsParallel().AsOrdered() where city.Population > 10000 select city) .Take(1000); PLINQ
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
Literatura • http://msdn.microsoft.com/en-us/library/dd460688.aspx PLINQ