niedziela, 9 maja 2010

PLINQ

Jak wiadomo, kilka tygodni temu wydano kolejną wersję .NET Framework’a a wraz z nią nowe Visual Studio. Zapoznając się z kolejnymi “feature’ami” czwartej już wersji Framework’a, postaram się napisać chociaż kilka zdań o tych najciekawszych.

Na pierwszy “ogień” pójdzie PLINQ. Cóż to zatem jest takiego? Otóż jest to nowa funkcjonalność polegająca na uruchamianiu zapytań LINQ dla obiektów równolegle (PLINQ = Parallel LINQ). Jak wiadomo obecnie producenci procesorów podążają w kierunku upakowania coraz większej ilości rdzeni na pojedynczym chipsecie, więc można przypuszczać, że w/w mechanizm szybko stanie popularny. Zwłaszcza, że użycie PLINQ (w najprostszym przypadku) jest banalne – sprowadza się ono do dopisania przed wywołaniem dowolnej metody “klasycznego” LINQ funkcji AsParallel().

Poniżej przykład:

var query = collection.AsParallel()
                .Select(el => el.ExpensiveMethod());

A teraz kilka słów jak to działa. Mianowicie do przestrzeni nazw System.Linq dodano nową klasę z metodami rozszerzającymi – ParallelEnumerable. Interfejs IEnumerable<T> rozszerza tylko o jedną metodę – wyżej już wspomnianą AsParallel(). Co ważne, metoda ta zwraca obiekt typu ParallelQuery<T>. I właśnie dla tej klasy metody rozszerzające znajdują się w klasie ParallelEnumerable – są tam wszystkie metody znane z “klasycznego” LINQ – jedyna różnica to zwracany obiekt – zamiast IEnumerable<T> mamy ParallelQuery<T>. Dzięki takiemu podejściu zrównoleglanie zapytań jest dziecinnie proste. Przykładowo mając zapytanie postaci:

var sum = collection.Where(el => el.IsCorrect())
                .Select(el => el.ExpensiveMethod())
                .Sum(el => el.Value);

zmiamy je w zapytanie wykonywane równoległe dopisując tylko np. na początku wywołania AsParallel():

var sum = collection.AsParallel()
                .Where(el => el.IsCorrect())
                .Select(el => el.ExpensiveMethod())
                .Sum(el => el.Value);

Często jest jednak tak, że nie całe zapytanie powinno być wykonywane równolegle – pewien fragment (ze względu np. na narzut na utworzenie wątków, itp.) może się wykonywać szybciej szeregowo. Aby zatem zrezygnować z dalszego wykonywania zapytania równolegle – ParallelEnumerable posiada specjalną metodę – AsSequential – po jej wywołaniu dalsza część zapytania będzie wykonywana szeregowo (metoda zwraca po prostu IEnumerable<T>, co powoduje, że dalsza część zapytania LINQ jest wykonywana “starym” sposobem). Przykładowo, mając następujące zapytanie:

var sum = collection.AsParallel()
                .Where(el => el.IsCorrect())
                .Select(el => el.ExpensiveMethod())
                .AsSequential()
                .FirstOrDefault(el => el.Value > 20);

Metody Where i Select zostaną wykonane równolegle, natomiast metoda FirstOrDefault będzie już wykonana sekwencyjnie.

To by było tyle wstępu o PLINQ, następnym razem postaram się opisać bardziej zaawansowane mechanizmy, czyli w jaki sposób sterować równoległym wykonywaniem zapytań.

Brak komentarzy:

Prześlij komentarz