Beställ bevarande i PLINQ
I PLINQ är målet att maximera prestandan samtidigt som korrektheten bibehålls. En fråga ska köras så snabbt som möjligt men ändå ge rätt resultat. I vissa fall kräver korrekthet att källsekvensens ordning bevaras. Beställningen kan dock vara beräkningsmässigt dyr. PLINQ bevarar därför som standard inte källsekvensens ordning. I det här avseendet liknar PLINQ LINQ till SQL, men är till skillnad från LINQ till Objekt, vilket bevarar ordningen.
Om du vill åsidosätta standardbeteendet kan du aktivera orderbevarande med hjälp av operatorn AsOrdered i källsekvensen. Du kan sedan inaktivera orderbevarande senare i frågan med hjälp AsUnordered av metoden . Med båda metoderna bearbetas frågan baserat på heuristiken som avgör om frågan ska köras som parallell eller sekventiell. Mer information finns i Förstå hastighet i PLINQ.
I följande exempel visas en oordnad parallell fråga som filtrerar för alla element som matchar ett villkor, utan att försöka sortera resultaten på något sätt.
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)
Den här frågan producerar inte nödvändigtvis de första 1 000 städerna i källsekvensen som uppfyller villkoret, utan snarare en uppsättning med 1 000 städer som uppfyller villkoret. PLINQ-frågeoperatorer partitionerar källsekvensen i flera underfrågor som bearbetas som samtidiga uppgifter. Om orderbevaring inte anges överlämnas resultatet från varje partition till nästa steg i frågan i godtycklig ordning. Dessutom kan en partition ge en delmängd av dess resultat innan den fortsätter att bearbeta de återstående elementen. Den resulterande ordningen kan vara olika varje gång. Programmet kan inte styra detta eftersom det beror på hur operativsystemet schemalägger trådarna.
I följande exempel åsidosätts standardbeteendet med hjälp av operatorn AsOrdered i källsekvensen. Detta säkerställer att Take metoden returnerar de första 1 000 städerna i källsekvensen som uppfyller villkoret.
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)
Den här frågan körs dock förmodligen inte lika snabbt som den osorterade versionen eftersom den måste hålla reda på den ursprungliga ordningen i partitionerna och vid sammanslagningstiden se till att ordningen är konsekvent. Därför rekommenderar vi att du endast använder AsOrdered när det krävs och endast för de delar av frågan som kräver det. När orderbevarande inte längre krävs kan du använda AsUnordered för att inaktivera det. I följande exempel uppnås detta genom att två frågor skapas.
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
Observera att PLINQ bevarar ordningen på en sekvens som genereras av order-imponerande operatorer för resten av frågan. Med andra ord behandlas operatorer som OrderBy och ThenBy som om de följdes av ett anrop till AsOrdered.
Frågeoperatorer och beställning
Följande frågeoperatorer introducerar orderbevarande i alla efterföljande åtgärder i en fråga eller tills anropas AsUnordered :
Följande PLINQ-frågeoperatorer kan i vissa fall kräva ordnade källsekvenser för att ge rätt resultat:
Vissa PLINQ-frågeoperatorer beter sig annorlunda, beroende på om deras källsekvens är ordnad eller osorterad. I följande tabell visas dessa operatorer.
Operator | Resultat när källsekvensen sorteras | Resultat när källsekvensen är oordnad |
---|---|---|
Aggregate | Nondeterministiska utdata för icke-associerande eller icke-kommutativa åtgärder | Nondeterministiska utdata för icke-associerande eller icke-kommutativa åtgärder |
All | Ej tillämpligt | Saknas |
Any | Saknas | Saknas |
AsEnumerable | Saknas | Ej tillämpligt |
Average | Nondeterministiska utdata för icke-associerande eller icke-kommutativa åtgärder | Nondeterministiska utdata för icke-associerande eller icke-kommutativa åtgärder |
Cast | Ordnade resultat | Osorterade resultat |
Concat | Ordnade resultat | Osorterade resultat |
Count | Ej tillämpligt | Saknas |
DefaultIfEmpty | Saknas | Ej tillämpligt |
Distinct | Ordnade resultat | Osorterade resultat |
ElementAt | Returnera angivet element | Godtyckligt element |
ElementAtOrDefault | Returnera angivet element | Godtyckligt element |
Except | Osorterade resultat | Osorterade resultat |
First | Returnera angivet element | Godtyckligt element |
FirstOrDefault | Returnera angivet element | Godtyckligt element |
ForAll | Kör icke-terministiskt parallellt | Kör icke-terministiskt parallellt |
GroupBy | Ordnade resultat | Osorterade resultat |
GroupJoin | Ordnade resultat | Osorterade resultat |
Intersect | Ordnade resultat | Osorterade resultat |
Join | Ordnade resultat | Osorterade resultat |
Last | Returnera angivet element | Godtyckligt element |
LastOrDefault | Returnera angivet element | Godtyckligt element |
LongCount | Ej tillämpligt | Saknas |
Min | Saknas | Ej tillämpligt |
OrderBy | Ändrar ordning på sekvensen | Startar nytt ordnat avsnitt |
OrderByDescending | Ändrar ordning på sekvensen | Startar nytt ordnat avsnitt |
Range | Inte tillämpligt (samma standard som AsParallel ) | Inte tillämpligt |
Repeat | Inte tillämpligt (samma standard som AsParallel) | Inte tillämpligt |
Reverse | Vänder | Gör ingenting |
Select | Ordnade resultat | Osorterade resultat |
Select (indexerat) | Ordnade resultat | Osorterade resultat. |
SelectMany | Ordnade resultat. | Osorterade resultat |
SelectMany (indexerat) | Ordnade resultat. | Osorterade resultat. |
SequenceEqual | Ordnad jämförelse | Osorterad jämförelse |
Single | Ej tillämpligt | Saknas |
SingleOrDefault | Saknas | Ej tillämpligt |
Skip | Hoppar över de första n elementen | Hoppar över alla n element |
SkipWhile | Ordnade resultat. | Nondeterministisk. Utför SkipWhile på den aktuella godtyckliga ordningen |
Sum | Nondeterministiska utdata för icke-associerande eller icke-kommutativa åtgärder | Nondeterministiska utdata för icke-associerande eller icke-kommutativa åtgärder |
Take | Tar de första n elementen |
Tar alla n element |
TakeWhile | Ordnade resultat | Nondeterministisk. Utför TakeWhile på den aktuella godtyckliga ordningen |
ThenBy | Tillägg OrderBy |
Tillägg OrderBy |
ThenByDescending | Tillägg OrderBy |
Tillägg OrderBy |
ToArray | Ordnade resultat | Osorterade resultat |
ToDictionary | Ej tillämpligt | Ej tillämpligt |
ToList | Ordnade resultat | Osorterade resultat |
ToLookup | Ordnade resultat | Osorterade resultat |
Union | Ordnade resultat | Osorterade resultat |
Where | Ordnade resultat | Osorterade resultat |
Where (indexerat) | Ordnade resultat | Osorterade resultat |
Zip | Ordnade resultat | Osorterade resultat |
Osorterade resultat blandas inte aktivt. De har helt enkelt inte någon särskild ordningslogik som tillämpas på dem. I vissa fall kan en osorterad fråga behålla ordningen på källsekvensen. För frågor som använder den indexerade Select-operatorn garanterar PLINQ att utdataelementen kommer ut i ordningen för att öka indexen, men ger inga garantier om vilka index som ska tilldelas till vilka element.