In PLINQ, the goal is to maximize performance while maintaining correctness. A query should run as fast as possible but still produce the correct results. In some cases, correctness requires the order of the source sequence to be preserved; however, ordering can be computationally expensive. Therefore, by default, PLINQ does not preserve the order of the source sequence. In this regard, PLINQ resembles LINQ to SQL, but is unlike LINQ to Objects, which does preserve ordering.
To override the default behavior, you can turn on order-preservation by using the AsOrdered operator on the source sequence. You can then turn off order preservation later in the query by using the AsUnordered method. With both methods, the query is processed based on the heuristics that determine whether to execute the query as parallel or as sequential. For more information, see Understanding Speedup in PLINQ.
The following example shows an unordered parallel query that filters for all the elements that match a condition, without trying to order the results in any way.
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)
This query does not necessarily produce the first 1000 cities in the source sequence that meet the condition, but rather some set of 1000 cities that meet the condition. PLINQ query operators partition the source sequence into multiple subsequences that are processed as concurrent tasks. If order preservation is not specified, the results from each partition are handed off to the next stage of the query in an arbitrary order. Also, a partition may yield a subset of its results before it continues to process the remaining elements. The resulting order may be different every time. Your application cannot control this because it depends on how the operating system schedules the threads.
The following example overrides the default behavior by using the AsOrdered operator on the source sequence. This ensures that the Take method returns the first 1000 cities in the source sequence that meet the condition.
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)
However, this query probably does not run as fast as the unordered version because it must keep track of the original ordering throughout the partitions and at merge time ensure that the ordering is consistent. Therefore, we recommend that you use AsOrdered only when it is required, and only for those parts of the query that require it. When order preservation is no longer required, use AsUnordered to turn it off. The following example achieves this by composing two queries.
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
Note that PLINQ preserves the ordering of a sequence produced by order-imposing operators for the rest of the query. In other words, operators such as OrderBy and ThenBy are treated as if they were followed by a call to AsOrdered.
Query Operators and OrderingThe following query operators introduce order preservation into all subsequent operations in a query, or until AsUnordered is called:
The following PLINQ query operators may in some cases require ordered source sequences to produce correct results:
Some PLINQ query operators behave differently, depending on whether their source sequence is ordered or unordered. The following table lists these operators.
Operator Result when the source sequence is ordered Result when the source sequence is unordered Aggregate Nondeterministic output for nonassociative or noncommutative operations Nondeterministic output for nonassociative or noncommutative operations All Not applicable Not applicable Any Not applicable Not applicable AsEnumerable Not applicable Not applicable Average Nondeterministic output for nonassociative or noncommutative operations Nondeterministic output for nonassociative or noncommutative operations Cast Ordered results Unordered results Concat Ordered results Unordered results Count Not applicable Not applicable DefaultIfEmpty Not applicable Not applicable Distinct Ordered results Unordered results ElementAt Return specified element Arbitrary element ElementAtOrDefault Return specified element Arbitrary element Except Unordered results Unordered results First Return specified element Arbitrary element FirstOrDefault Return specified element Arbitrary element ForAll Executes nondeterministically in parallel Executes nondeterministically in parallel GroupBy Ordered results Unordered results GroupJoin Ordered results Unordered results Intersect Ordered results Unordered results Join Ordered results Unordered results Last Return specified element Arbitrary element LastOrDefault Return specified element Arbitrary element LongCount Not applicable Not applicable Min Not applicable Not applicable OrderBy Reorders the sequence Starts new ordered section OrderByDescending Reorders the sequence Starts new ordered section Range Not applicable (same default as AsParallel ) Not applicable Repeat Not applicable (same default as AsParallel) Not applicable Reverse Reverses Does nothing Select Ordered results Unordered results Select (indexed) Ordered results Unordered results. SelectMany Ordered results. Unordered results SelectMany (indexed) Ordered results. Unordered results. SequenceEqual Ordered comparison Unordered comparison Single Not applicable Not applicable SingleOrDefault Not applicable Not applicable Skip Skips first n elements Skips any n elements SkipWhile Ordered results. Nondeterministic. Performs SkipWhile on the current arbitrary order Sum Nondeterministic output for nonassociative or noncommutative operations Nondeterministic output for nonassociative or noncommutative operations Take Takes firstn
elements Takes any n
elements TakeWhile Ordered results Nondeterministic. Performs TakeWhile on the current arbitrary order ThenBy Supplements OrderBy
Supplements OrderBy
ThenByDescending Supplements OrderBy
Supplements OrderBy
ToArray Ordered results Unordered results ToDictionary Not applicable Not applicable ToList Ordered results Unordered results ToLookup Ordered results Unordered results Union Ordered results Unordered results Where Ordered results Unordered results Where (indexed) Ordered results Unordered results Zip Ordered results Unordered results
Unordered results are not actively shuffled; they simply do not have any special ordering logic applied to them. In some cases, an unordered query may retain the ordering of the source sequence. For queries that use the indexed Select operator, PLINQ guarantees that the output elements will come out in the order of increasing indices, but makes no guarantees about which indices will be assigned to which elements.
See alsoRetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4