Kako raditi s paralelnim LINQ-om u C #

Upit integriran u jezik, poznat i kao LINQ, cjevovod je za izvršavanje upita koji dodaje mogućnosti upita jezicima ciljanim na upravljano okruženje .Net-a. Paralelni LINQ ili PLINQ je mehanizam za izvršavanje upita koji se pokreće na vrhu upravljanog okruženja .Net-a i koristi prednosti višestrukih procesora ili jezgri u vašem računalnom sustavu za paralelno izvršavanje upita. Drugim riječima, omogućuje vam optimizaciju upita dijeljenjem na dijelove tako da se ti dijelovi izvršavaju paralelno i time poboljšavaju performanse upita.

PLINQ je proširenje za LINQ i predstavljen je kao dio .Net Framework 4. To je Microsoftov mehanizam za izvršavanje upita i dio je biblioteke paralelnih proširenja. Knjižnica paralelnih proširenja zauzvrat se sastoji od TPL-a (knjižnica paralelnih zadataka) i PLINQ. Microsoft je pružio podršku za paralelno programiranje u .Net Frameworku kako bi iskoristio prednosti višejezgrenih sustava. Da bi se iskoristile mogućnosti paralelnog programiranja, u .Net Framework 4 uvedena je nova klasa pod nazivom Parallel.

PLINQ je dobar izbor u računalno vezanim operacijama. Ali, o čemu se radi i koji su problemi koje može riješiti? Je li prikladno koristiti ga umjesto LINQ-a kad god moramo tražiti podatke? O svemu bismo razgovarali u trenutku, ali prvo shvatimo kako PLINQ djeluje iza kulisa. PLINQ djeluje tako da particionira izvor podataka ili ulaz na dijelove koji se pak izvršavaju različitim nitima.

Sad malo koda

Razmotrite sljedeći LINQ upit.

var data = from e in employees

           where e.FirstName.StartsWith("J")

           select e;

Gornji upit možete jednostavno pretvoriti u PLINQ upit pomoću metode proširenja AsParallel. Imajte na umu da je AsParallel metoda produženja klase System.Linq.ParallelEnumerable.

var data = from e in employees.AsParallel()

           where e.FirstName.StartsWith("J")

           select e;

Ako želite sačuvati redoslijed rezultata upita, možete iskoristiti metodu AsOrdered.

var data = from e in employees.AsParallel().AsOrdered()

           where e.FirstName.StartsWith("J")

           select e;

Također možete sačuvati redoslijed podataka koji se vraćaju kao rezultat izvršavanja PLINQ upita prosljeđivanjem QueryOptions.PreserveOrdering kao parametra metodi AsParallel.

var data = from e in employees.AsParallel(QueryOptions.PreserveOrdering)

           where e.FirstName.StartsWith("J")

           select e;

Imajte na umu da uporaba metode AsParallel () nije poželjna za male zbirke - radije bi radila sporije u usporedbi s normalnim upitom. Što ako želite forsirati paralelizam? To se ipak ne preporučuje, ali možete postići metodu proširenja WithExecutionMode da biste to postigli. Evo primjera koji to ilustrira.

var data = from e in employees.AsParallel().WithExecutionMode

                (ParallelExecutionMode.ForceParallelism)

           where e.FirstName.StartsWith("J")

           select e;

Imajte na umu da je ParallelExecutionMode nabrajanje koje je dostupno kao dio prostora imena System.Linq i može imati jednu od ovih vrijednosti: Default i ForceParallelism. Ako specificirate Default kao parametar za metodu produženja WithExecutionMode, PLINQ će paralelno izvršavati upit ako je vidljivo poboljšanje performansi u paralelnom izvršavanju upita. Ako nije, PLINQ će izvršiti upit baš kao i LINQ upit. Suprotno tome, ako specificirate ForeParallelism kao parametar metode produženja WithExecutionMode, PLINQ će paralelno izvršavati upit čak i ako to možda nanese kazna izvedbe.

Kako mogu ograničiti stupanj paralelizma?

Također biste trebali biti svjesni još jednog povezanog koncepta: stupanj paralelizma. Ovo je nepotpisani cijeli broj koji označava maksimalan broj procesora koje bi vaš PLINQ upit trebao iskoristiti dok je u izvršenju. Drugim riječima, stupanj paralelizma je cijeli broj koji označava maksimalan broj zadataka koji bi se istovremeno izvršavali za obradu upita.

Inače, zadana vrijednost stupnja paralelizma je 64, što znači da PLINQ može iskoristiti najviše 64 procesora u vašem sustavu. Evo kako možete ograničiti stupanj paralelizma u PLINQ-u na dva procesora u vašem sustavu.

var data = from e in employees.AsParallel().WithDegreeOfParallelism(2)

           where e.FirstName.StartsWith("J")

           select e;

Primijetite kako je broj procesora proslijeđen kao argument metodi WithDegreeofParallelism. Trebali biste navesti veću vrijednost za stupanj paralelizma za poboljšanje izvedbe ako vaš upit izvodi više neobračunatih, tj. Ne-CPU vezanih poslova.

Toplo preporučujem čitanje dokumenta "Obrasci paralelnog programiranja" Stephena Touba. Pruža detaljnu raspravu o paralelnim programskim obrascima u .Netu.