Sdílet prostřednictvím


Možnosti sloučení v PLINQ

Když se dotaz spouští paralelně, PLINQ rozdělí zdrojovou sekvenci tak, aby více vláken fungovalo na různých částech souběžně, obvykle na samostatných vláknech. Pokud se mají výsledky spotřebovávat na jednom vlákně, například ve foreach smyčce (For Each v jazyce Visual Basic), musí být výsledky z každého vlákna sloučeny zpět do jedné sekvence. Druh sloučení, který PLINQ provádí, závisí na operátorech, které jsou přítomné v dotazu. Například operátory, které pro výsledky ukládají nové pořadí, musí ukládat všechny prvky do vyrovnávací paměti ze všech vláken. Z pohledu spotřebitelského vlákna (což je také uživatel aplikace) může plně vyrovnaný dotaz běžet po znatelnou dobu, než vytvoří první výsledek. Ostatní operátory jsou ve výchozím nastavení částečně ukládány do vyrovnávací paměti; své výsledky poskytují v dávkách. Jeden operátor ForAll není ve výchozím nastavení uložen do vyrovnávací paměti. Poskytuje všechny prvky ze všech vláken okamžitě.

WithMergeOptions Pomocí metody, jak je znázorněno v následujícím příkladu, můžete poskytnout nápovědu pro PLINQ, která označuje, jaký druh slučování provést.

var scanLines = from n in nums.AsParallel()
                    .WithMergeOptions(ParallelMergeOptions.NotBuffered)
                where n % 2 == 0
                select ExpensiveFunc(n);
Dim scanlines = From n In nums.AsParallel().WithMergeOptions(ParallelMergeOptions.NotBuffered)
                Where n Mod 2 = 0
                Select ExpensiveFunc(n)

Úplný příklad naleznete v tématu Postupy: Určení možností sloučení v PLINQ.

Pokud konkrétní dotaz požadovanou možnost nepodporuje, bude tato možnost ignorována. Ve většině případů není nutné zadat možnost sloučení pro dotaz PLINQ. Nicméně v některých případech můžete zjistit na základě testování a měření, že dotaz se nejlépe provádí v nedefinovaném režimu. Běžným použitím této možnosti je vynucení operátoru slučování bloků dat streamovat výsledky za účelem zajištění responzivního uživatelského rozhraní.

Možnosti paralelního sloučení

Výčet ParallelMergeOptions obsahuje následující možnosti, které určují, u podporovaných obrazců dotazu, jak se konečný výstup dotazu vytvoří, když se výsledky získají na jednom vlákně:

  • Not Buffered

    Tato NotBuffered možnost způsobí, že se každý zpracovaný prvek vrátí z každého vlákna, jakmile se vytvoří. Toto chování je podobné "streamování" výstupu. AsOrdered Pokud je operátor v dotazu, NotBuffered zachová pořadí zdrojových prvků. I když NotBuffered se začnou zobrazovat výsledky hned, jak budou dostupné, může být celková doba, po kterou se všechny výsledky vytvoří, delší, než když použijete některou z ostatních možností sloučení.

  • Auto Buffered

    Tato AutoBuffered možnost způsobí, že dotaz shromáždí prvky do vyrovnávací paměti a pak pravidelně najednou předá obsah vyrovnávací paměti do spotřebovávajícího vlákna. To je analogické k dodávání zdrojových dat v "blocích" místo použití chování NotBuffered pomocí proudového režimu. AutoBuffered může trvat déle, než NotBuffered aby byl první prvek dostupný na spotřebovávajícím vlákně. Velikost vyrovnávací paměti a přesné chování při zpracování nelze konfigurovat a může se lišit v závislosti na různých faktorech, které souvisejí s dotazem.

  • FullyBuffered

    Tato FullyBuffered možnost způsobí, že se výstup celého dotazu uloží do vyrovnávací paměti před tím, než se vrátí některý z prvků. Pokud použijete tuto možnost, může trvat déle, než bude první prvek dostupný ve vlákně s využitím, ale úplné výsledky se můžou vytvořit rychleji než pomocí ostatních možností.

Operátory dotazů, které podporují možnosti sloučení

Následující tabulka uvádí operátory, které podporují všechny režimy možností sloučení, s výhradou zadaných omezení.

Operátor Omezení
AsEnumerable Žádné
Cast Žádné
Concat Neřazené dotazy, které mají pouze zdroj pole nebo seznamu.
DefaultIfEmpty Žádné
OfType Žádné
Reverse Neřazené dotazy, které mají pouze zdroj pole nebo seznamu.
Select Žádné
SelectMany Žádné
Skip Žádné
Take Žádné
Where Žádné

Všechny ostatní operátory dotazu PLINQ můžou ignorovat možnosti sloučení poskytnuté uživatelem. Některé operátory dotazů, například Reverse a OrderBy, nemohou přinést žádné prvky, dokud nebyly všechny vytvořeny a znovu seřazeny. Proto pokud ParallelMergeOptions se použije v dotazu, který obsahuje také operátor, například Reverse, slučovací chování se v dotazu nepoužije, dokud tento operátor nevygeneruje výsledky.

Schopnost některých operátorů zpracovávat možnosti sloučení závisí na typu zdrojové sekvence a na tom, jestli AsOrdered byl operátor použit dříve v dotazu. ForAll je vždy NotBuffered ; předává své prvky okamžitě. OrderBy je vždy FullyBuffered; musí seřadit celý seznam, než vrátí výsledek.

Viz také