Как да работя с Parallel LINQ в C #

Езиково интегрирана заявка, известна също като LINQ, е тръбопровод за изпълнение на заявки, който добавя възможности за заявки към езици, насочени към управляваната среда на .Net. Parallel LINQ или PLINQ е механизъм за изпълнение на заявки, който се изпълнява върху управляваната среда на .Net и се възползва от множеството процесори или ядра във вашата компютърна система за паралелно изпълнение на заявките. С други думи, това ви позволява да оптимизирате вашите заявки, като ги разделите на части, така че да изпълнявате тези части паралелно и следователно да повишите производителността на заявката.

PLINQ е разширение на LINQ и е въведено като част от .Net Framework 4. Това е механизъм за изпълнение на заявки от Microsoft и е част от библиотеката за паралелни разширения. Библиотеката за паралелни разширения от своя страна се състои от TPL (Task Parallel Library) и PLINQ. Microsoft предостави поддръжка за паралелно програмиране в .Net Framework, за да се възползва от предимствата на многоядрените системи. За да се възползва от възможностите за паралелно програмиране, в .Net Framework 4 беше въведен нов клас, наречен Parallel.

PLINQ е добър избор при операции, свързани с изчисления. Но за какво става въпрос и какви са проблемите, които може да реши? Подходящо ли е да го използваме вместо LINQ, когато имаме нужда от данни? Бихме обсъдили всичко това след малко, но нека първо разберем как PLINQ работи зад кулисите. PLINQ работи чрез разделяне на източника на данни или въвеждането на парчета, което от своя страна се изпълнява от различни нишки.

Малко код сега

Обмислете следната заявка LINQ.

var data = from e in employees

           where e.FirstName.StartsWith("J")

           select e;

Можете лесно да конвертирате горната заявка в заявка PLINQ, като използвате метода за разширение AsParallel. Имайте предвид, че AsParallel е метод за разширение на класа System.Linq.ParallelEnumerable.

var data = from e in employees.AsParallel()

           where e.FirstName.StartsWith("J")

           select e;

Ако искате да запазите реда на резултата от заявката, можете да се възползвате от метода AsOrdered.

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

           where e.FirstName.StartsWith("J")

           select e;

Можете също така да запазите реда на данните, които се връщат в резултат на изпълнението на заявката PLINQ, като предадете QueryOptions.PreserveOrdering като параметър на метода AsParallel.

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

           where e.FirstName.StartsWith("J")

           select e;

Имайте предвид, че използването на метода AsParallel () не е препоръчително за малки колекции - по-скоро ще работи по-бавно в сравнение с нормална заявка. Ами ако искате да наложите паралелизъм? Това обаче не се препоръчва, но можете да използвате метода за разширение WithExecutionMode, за да постигнете това. Ето пример, който илюстрира това.

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

                (ParallelExecutionMode.ForceParallelism)

           where e.FirstName.StartsWith("J")

           select e;

Имайте предвид, че ParallelExecutionMode е изброяване, което е достъпно като част от пространството от имена System.Linq и може да има една от следните стойности: Default и ForceParallelism. Ако посочите По подразбиране като параметър за метода за разширение WithExecutionMode, PLINQ ще изпълни заявката паралелно, ако подобрението в производителността е очевидно при паралелното изпълнение на заявката. Ако не, PLINQ ще изпълни заявката точно като заявка LINQ. Напротив, ако посочите ForeParallelism като параметър на метода за разширение WithExecutionMode, PLINQ ще изпълни заявката паралелно, дори ако това може да доведе до наказание за изпълнение.

Как да огранича степента на паралелизъм?

Трябва да знаете и друга свързана концепция: степен на паралелизъм. Това е неподписано цяло число, което обозначава максималния брой процесори, от които вашата PLINQ заявка трябва да се възползва, докато е в изпълнение. С други думи, степента на паралелизъм е цяло число, което обозначава максималния брой задачи, които биха били изпълнени едновременно за обработка на заявка.

Между другото, стойността по подразбиране на степента на паралелизъм е 64, което предполага, че PLINQ може да използва максимум 64 процесора във вашата система. Ето как можете да ограничите степента на паралелизъм в PLINQ до два процесора във вашата система.

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

           where e.FirstName.StartsWith("J")

           select e;

Обърнете внимание как броят на процесорите е предаден като аргумент на метода WithDegreeofParallelism. Трябва да посочите по-висока стойност за степента на паралелност за повишаване на производителността, ако вашата заявка изпълнява по-необвързана, т.е. не свързана с процесора работа.

Горещо препоръчвам да прочетете документа „Модели на паралелно програмиране“ от Стивън Туб. Той предоставя задълбочена дискусия за паралелните модели на програмиране в .Net.