Rendelésmegőrzés a PLINQ-ban
A PLINQ-ban a cél a teljesítmény maximalizálása a helyesség fenntartása mellett. A lekérdezésnek a lehető leggyorsabban kell futnia, de továbbra is a megfelelő eredményeket kell eredményeznie. Bizonyos esetekben a helyesség megköveteli a forrásütemezés sorrendjének megőrzését; a megrendelés azonban számításilag költséges lehet. Ezért a PLINQ alapértelmezés szerint nem őrzi meg a forrásütemezés sorrendjét. Ebben a tekintetben a PLINQ a LINQ-hoz hasonlít az SQL-hez, de nem hasonlít a LINQ-ra az objektumokhoz, ami megőrzi a sorrendet.
Az alapértelmezett viselkedés felülbírálásához bekapcsolhatja a sorrend megőrzését a AsOrdered forrásütemezés operátorával. Ezután a metódussal AsUnordered kikapcsolhatja a rendelések megőrzését a lekérdezés későbbi részében. Mindkét módszer esetén a lekérdezés feldolgozása a heurisztika alapján történik, amely meghatározza, hogy a lekérdezést párhuzamosként vagy szekvenciálisként kell-e végrehajtani. További információ: Understanding Speedup in PLINQ.
Az alábbi példa egy rendezetlen párhuzamos lekérdezést mutat be, amely a feltételnek megfelelő összes elemre szűr anélkül, hogy bármilyen módon megpróbálná rendezni az eredményeket.
var cityQuery =
(from city in cities.AsParallel()
where city.Population > 10000
select city).Take(1000);
Dim cityQuery = From city In cities.AsParallel()
Where city.Population > 10000
Take (1000)
Ez a lekérdezés nem feltétlenül hozza létre az első 1000 várost a forrásütemezésben, amely megfelel a feltételnek, hanem néhány 1000 városból, amelyek megfelelnek a feltételnek. A PLINQ lekérdezési operátorok több részügyre particionálják a forrásütemezést, amelyeket egyidejű feladatként dolgoznak fel. Ha a sorrend megőrzése nincs megadva, az egyes partíciók eredményei tetszőleges sorrendben kerülnek átadásra a lekérdezés következő szakaszára. A partíciók az eredmények egy részhalmazát is eredményezhetik, mielőtt folytatják a fennmaradó elemek feldolgozását. Az eredményként kapott sorrend minden alkalommal eltérő lehet. Az alkalmazás ezt nem tudja szabályozni, mert attól függ, hogy az operációs rendszer hogyan ütemezi a szálakat.
Az alábbi példa felülírja az alapértelmezett viselkedést a AsOrdered forrásütemezés operátorának használatával. Ez biztosítja, hogy a Take metódus a forrásütemezés első 1000 városát adja vissza, amelyek megfelelnek a feltételnek.
var orderedCities =
(from city in cities.AsParallel().AsOrdered()
where city.Population > 10000
select city).Take(1000);
Dim orderedCities = From city In cities.AsParallel().AsOrdered()
Where city.Population > 10000
Take (1000)
Ez a lekérdezés azonban valószínűleg nem fut olyan gyorsan, mint a rendezetlen verzió, mert nyomon kell követnie az eredeti sorrendet a partíciókon, és az egyesítéskor gondoskodnia kell arról, hogy a rendezés konzisztens legyen. Ezért azt javasoljuk, hogy csak akkor használja AsOrdered , ha szükséges, és csak a lekérdezés azon részeire, amelyek megkövetelik. Ha a rendelések megőrzésére már nincs szükség, kapcsolja AsUnordered ki. Az alábbi példa ezt két lekérdezés írásával éri el.
var orderedCities2 =
(from city in cities.AsParallel().AsOrdered()
where city.Population > 10000
select city).Take(1000);
var finalResult =
from city in orderedCities2.AsUnordered()
join p in people.AsParallel()
on city.Name equals p.CityName into details
from c in details
select new
{
city.Name,
Pop = city.Population,
c.Mayor
};
foreach (var city in finalResult) { /*...*/ }
Dim orderedCities2 = From city In cities.AsParallel().AsOrdered()
Where city.Population > 10000
Select city
Take (1000)
Dim finalResult = From city In orderedCities2.AsUnordered()
Join p In people.AsParallel() On city.Name Equals p.CityName
Select New With {.Name = city.Name, .Pop = city.Population, .Mayor = city.Mayor}
For Each city In finalResult
Console.WriteLine(city.Name & ":" & city.Pop & ":" & city.Mayor)
Next
Vegye figyelembe, hogy a PLINQ megőrzi egy sorrendbe állítva a lekérdezés többi részében a rendelési impozáns operátorok által előállított sorrendet. Más szóval az olyan operátorokat, mint OrderBy például a ThenBy rendszer úgy kezeli őket, mintha egy hívás AsOrderedkövette volna őket.
Lekérdezési operátorok és rendezés
A következő lekérdezési operátorok a lekérdezés minden további műveletében bevezetik a sorrend megőrzését, vagy amíg meg nem AsUnordered hívják:
A következő PLINQ-lekérdezési operátorok bizonyos esetekben rendezett forrásütemezéseket igényelhetnek a helyes eredmények eléréséhez:
Egyes PLINQ-lekérdezési operátorok eltérően viselkednek attól függően, hogy a forrásütemezés rendezett vagy rendezetlen. Az alábbi táblázat felsorolja ezeket az operátorokat.
Operátor | A forrásütemezés sorrendjének eredménye | Eredmény, ha a forrásütemezés rendezetlen |
---|---|---|
Aggregate | Nemdeterminista kimenet nem társító vagy nem kommutatív műveletekhez | Nemdeterminista kimenet nem társító vagy nem kommutatív műveletekhez |
All | Nem alkalmazható | Nem alkalmazható |
Any | Nem alkalmazható | Nem alkalmazható |
AsEnumerable | Nem alkalmazható | Nem alkalmazható |
Average | Nemdeterminista kimenet nem társító vagy nem kommutatív műveletekhez | Nemdeterminista kimenet nem társító vagy nem kommutatív műveletekhez |
Cast | Rendezett eredmények | Rendezetlen eredmények |
Concat | Rendezett eredmények | Rendezetlen eredmények |
Count | Nem alkalmazható | Nem alkalmazható |
DefaultIfEmpty | Nem alkalmazható | Nem alkalmazható |
Distinct | Rendezett eredmények | Rendezetlen eredmények |
ElementAt | Megadott elem visszaadva | Tetszőleges elem |
ElementAtOrDefault | Megadott elem visszaadva | Tetszőleges elem |
Except | Rendezetlen eredmények | Rendezetlen eredmények |
First | Megadott elem visszaadva | Tetszőleges elem |
FirstOrDefault | Megadott elem visszaadva | Tetszőleges elem |
ForAll | Nemdeterminisztikusan, párhuzamosan hajtja végre | Nemdeterminisztikusan, párhuzamosan hajtja végre |
GroupBy | Rendezett eredmények | Rendezetlen eredmények |
GroupJoin | Rendezett eredmények | Rendezetlen eredmények |
Intersect | Rendezett eredmények | Rendezetlen eredmények |
Join | Rendezett eredmények | Rendezetlen eredmények |
Last | Megadott elem visszaadva | Tetszőleges elem |
LastOrDefault | Megadott elem visszaadva | Tetszőleges elem |
LongCount | Nem alkalmazható | Nem alkalmazható |
Min | Nem alkalmazható | Nem alkalmazható |
OrderBy | A sorrend átrendezése | Új rendezett szakasz indítása |
OrderByDescending | A sorrend átrendezése | Új rendezett szakasz indítása |
Range | Nem alkalmazható (az alapértelmezett érték ugyanaz, mint AsParallel a ) | Nem alkalmazható |
Repeat | Nem alkalmazható (az alapértelmezett érték ugyanaz, mint AsParallela ) | Nem alkalmazható |
Reverse | Megfordítja | Nem tesz semmit |
Select | Rendezett eredmények | Rendezetlen eredmények |
Select (indexelt) | Rendezett eredmények | Rendezetlen eredmények. |
SelectMany | Rendezett eredmények. | Rendezetlen eredmények |
SelectMany (indexelt) | Rendezett eredmények. | Rendezetlen eredmények. |
SequenceEqual | Rendezett összehasonlítás | Rendezetlen összehasonlítás |
Single | Nem alkalmazható | Nem alkalmazható |
SingleOrDefault | Nem alkalmazható | Nem alkalmazható |
Skip | Az első n elemek kihagyása | Kihagyja az n elemeket |
SkipWhile | Rendezett eredmények. | Nemdeterminista. A SkipWhile végrehajtása az aktuális tetszőleges sorrendben |
Sum | Nemdeterminista kimenet nem társító vagy nem kommutatív műveletekhez | Nemdeterminista kimenet nem társító vagy nem kommutatív műveletekhez |
Take | Első n elemeket vesz fel |
Bármilyen n elemet átvesz |
TakeWhile | Rendezett eredmények | Nemdeterminista. TakeWhile végrehajtása az aktuális tetszőleges sorrendben |
ThenBy | Kiegészítők OrderBy |
Kiegészítők OrderBy |
ThenByDescending | Kiegészítők OrderBy |
Kiegészítők OrderBy |
ToArray | Rendezett eredmények | Rendezetlen eredmények |
ToDictionary | Nem alkalmazható | Nem alkalmazható |
ToList | Rendezett eredmények | Rendezetlen eredmények |
ToLookup | Rendezett eredmények | Rendezetlen eredmények |
Union | Rendezett eredmények | Rendezetlen eredmények |
Where | Rendezett eredmények | Rendezetlen eredmények |
Where (indexelt) | Rendezett eredmények | Rendezetlen eredmények |
Zip | Rendezett eredmények | Rendezetlen eredmények |
A rendezetlen eredmények nincsenek aktívan elfojtva; egyszerűen nincsenek speciális rendezési logikák alkalmazva rájuk. Bizonyos esetekben a rendezetlen lekérdezések megtarthatják a forrásütemezés sorrendjét. Az indexelt Select operátort használó lekérdezések esetében a PLINQ garantálja, hogy a kimeneti elemek az indexek növelésének sorrendjében jelennek meg, de nem garantálja, hogy mely indexek mely elemekhez lesznek hozzárendelve.