Conservazione dell'ordine in PLINQOrder Preservation in PLINQ

In PLINQ, l'obiettivo è ottimizzare le prestazioni, mantenendo la correttezza.In PLINQ, the goal is to maximize performance while maintaining correctness. Una query deve essere eseguita il più velocemente possibile ma comunque produrre i risultati corretti.A query should run as fast as possible but still produce the correct results. In alcuni casi, la correttezza richiede il mantenimento dell'ordine della sequenza di origine, ma l'ordinamento può essere oneroso a livello di risorse di calcolo.In some cases, correctness requires the order of the source sequence to be preserved; however, ordering can be computationally expensive. Pertanto, per impostazione predefinita, PLINQ non mantiene l'ordine della sequenza di origine.Therefore, by default, PLINQ does not preserve the order of the source sequence. Da questo punto di vista, PLINQ è simile a LINQ to SQLLINQ to SQL, ma differisce da LINQ to Objects, che mantiene l'ordinamento.In this regard, PLINQ resembles LINQ to SQLLINQ to SQL, but is unlike LINQ to Objects, which does preserve ordering.

Per eseguire l'override del comportamento predefinito, è possibile attivare il mantenimento dell'ordine usando l'operatore AsOrdered nella sequenza di origine.To override the default behavior, you can turn on order-preservation by using the AsOrdered operator on the source sequence. È quindi possibile disattivare il mantenimento dell'ordine in un secondo momento nella query usando il metodo AsUnordered.You can then turn off order preservation later in the query by using the AsUnordered method. Con entrambi i metodi, la query viene elaborata in base alle regole euristiche che determinano se scegliere l'esecuzione parallela o sequenziale per la query.With both methods, the query is processed based on the heuristics that determine whether to execute the query as parallel or as sequential. Per altre informazioni, vedere Informazioni sull'aumento di velocità in PLINQ.For more information, see Understanding Speedup in PLINQ.

L'esempio seguente mostra una query parallela non ordinata che applica un filtro per individuare tutti gli elementi che soddisfano una condizione, senza tentare di ordinare i risultati in alcun modo.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)

Questa query non produce necessariamente le prime 1000 città nella sequenza di origine che soddisfano la condizione, ma piuttosto un set di 1000 città che soddisfano la condizione.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. Gli operatori di query PLINQ partizionano la sequenza di origine in più sottosequenze che vengono elaborate come attività simultanee.PLINQ query operators partition the source sequence into multiple subsequences that are processed as concurrent tasks. Se non viene specificato di mantenere l'ordine, i risultati di ogni partizione vengono passati alla fase successiva della query in ordine arbitrario.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. Inoltre, una partizione potrebbe produrre un subset di risultati prima di continuare a elaborare gli elementi rimanenti.Also, a partition may yield a subset of its results before it continues to process the remaining elements. L'ordine risultante potrebbe essere diverso ogni volta.The resulting order may be different every time. L'applicazione non può controllare questo comportamento perché dipende dalla modalità di pianificazione dei thread del sistema operativo.Your application cannot control this because it depends on how the operating system schedules the threads.

Nell'esempio seguente viene eseguito l'override del comportamento predefinito tramite l'operatore AsOrdered nella sequenza di origine.The following example overrides the default behavior by using the AsOrdered operator on the source sequence. Ciò assicura che il metodo Take restituisca le prime 1000 città nella sequenza di origine che soddisfano la condizione.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)

Tuttavia, questa query probabilmente non viene eseguita altrettanto velocemente della versione non ordinata perché deve tenere traccia dell'ordine originale per tutte le partizioni e assicurarsi che l'ordine sia coerente al momento dell'unione.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. È pertanto consigliabile usare AsOrdered solo quando è necessario e solo per le parti della query che lo richiedono.Therefore, we recommend that you use AsOrdered only when it is required, and only for those parts of the query that require it. Quando non occorre più mantenere l'ordine, usare AsUnordered per disattivare questo comportamento.When order preservation is no longer required, use AsUnordered to turn it off. L'esempio ottiene questo risultato tramite la composizione di due query.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 { Name = city.Name, Pop = city.Population, Mayor = 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

Si noti che PLINQ mantiene l'ordinamento di una sequenza da operatori che impongono l'ordine per il resto della query.Note that PLINQ preserves the ordering of a sequence produced by order-imposing operators for the rest of the query. In altre parole, gli operatori come OrderBy e ThenBy vengono gestiti come se fossero seguiti da una chiamata a AsOrdered.In other words, operators such as OrderBy and ThenBy are treated as if they were followed by a call to AsOrdered.

Operatori di query e di ordinamentoQuery Operators and Ordering

Gli operatori di query seguenti introducono il mantenimento dell'ordine in tutte le successive operazioni in una query o fino a quando non viene chiamato AsUnordered:The following query operators introduce order preservation into all subsequent operations in a query, or until AsUnordered is called:

Gli operatori di query PLINQ seguenti possono richiedere in alcuni casi sequenze di origine ordinate per produrre risultati corretti:The following PLINQ query operators may in some cases require ordered source sequences to produce correct results:

Alcuni operatori di query PLINQ si comportano in modo diverso, a seconda che la sequenza di origine sia ordinata o non ordinata.Some PLINQ query operators behave differently, depending on whether their source sequence is ordered or unordered. Questi operatori sono elencati nella tabella seguente.The following table lists these operators.

OperatoreOperator Risultato quando la sequenza di origine è ordinataResult when the source sequence is ordered Risultato quando la sequenza di origine non è ordinataResult when the source sequence is unordered
Aggregate Output non deterministico per operazioni non associative o non commutativeNondeterministic output for nonassociative or noncommutative operations Output non deterministico per operazioni non associative o non commutativeNondeterministic output for nonassociative or noncommutative operations
All Non applicabileNot applicable Non applicabileNot applicable
Any Non applicabileNot applicable Non applicabileNot applicable
AsEnumerable Non applicabileNot applicable Non applicabileNot applicable
Average Output non deterministico per operazioni non associative o non commutativeNondeterministic output for nonassociative or noncommutative operations Output non deterministico per operazioni non associative o non commutativeNondeterministic output for nonassociative or noncommutative operations
Cast Risultati ordinatiOrdered results Risultati non ordinatiUnordered results
Concat Risultati ordinatiOrdered results Risultati non ordinatiUnordered results
Count Non applicabileNot applicable Non applicabileNot applicable
DefaultIfEmpty Non applicabileNot applicable Non applicabileNot applicable
Distinct Risultati ordinatiOrdered results Risultati non ordinatiUnordered results
ElementAt Restituisce l'elemento specificatoReturn specified element Elemento arbitrarioArbitrary element
ElementAtOrDefault Restituisce l'elemento specificatoReturn specified element Elemento arbitrarioArbitrary element
Except Risultati non ordinatiUnordered results Risultati non ordinatiUnordered results
First Restituisce l'elemento specificatoReturn specified element Elemento arbitrarioArbitrary element
FirstOrDefault Restituisce l'elemento specificatoReturn specified element Elemento arbitrarioArbitrary element
ForAll Esecuzione non deterministica in paralleloExecutes nondeterministically in parallel Esecuzione non deterministica in paralleloExecutes nondeterministically in parallel
GroupBy Risultati ordinatiOrdered results Risultati non ordinatiUnordered results
GroupJoin Risultati ordinatiOrdered results Risultati non ordinatiUnordered results
Intersect Risultati ordinatiOrdered results Risultati non ordinatiUnordered results
Join Risultati ordinatiOrdered results Risultati non ordinatiUnordered results
Last Restituisce l'elemento specificatoReturn specified element Elemento arbitrarioArbitrary element
LastOrDefault Restituisce l'elemento specificatoReturn specified element Elemento arbitrarioArbitrary element
LongCount Non applicabileNot applicable Non applicabileNot applicable
Min Non applicabileNot applicable Non applicabileNot applicable
OrderBy Riordina la sequenzaReorders the sequence Avvia una nuova sezione ordinataStarts new ordered section
OrderByDescending Riordina la sequenzaReorders the sequence Avvia una nuova sezione ordinataStarts new ordered section
Range Non applicabile (stessa impostazione predefinita di AsParallel)Not applicable (same default as AsParallel ) Non applicabileNot applicable
Repeat Non applicabile (stessa impostazione predefinita di AsParallel)Not applicable (same default as AsParallel) Non applicabileNot applicable
Reverse InverteReverses Non effettua alcuna operazione.Does nothing
Select Risultati ordinatiOrdered results Risultati non ordinatiUnordered results
Select (indicizzato)Select (indexed) Risultati ordinatiOrdered results Risultati non ordinatiUnordered results.
SelectMany Risultati ordinatiOrdered results. Risultati non ordinatiUnordered results
SelectMany (indicizzato)SelectMany (indexed) Risultati ordinatiOrdered results. Risultati non ordinatiUnordered results.
SequenceEqual Confronto ordinatoOrdered comparison Confronto non ordinatoUnordered comparison
Single Non applicabileNot applicable Non applicabileNot applicable
SingleOrDefault Non applicabileNot applicable Non applicabileNot applicable
Skip Ignora i primi elementi nSkips first n elements Ignora tutti gli elementi nSkips any n elements
SkipWhile Risultati ordinatiOrdered results. Non deterministicoNondeterministic. Esegue SkipWhile sull'ordine arbitrario correntePerforms SkipWhile on the current arbitrary order
Sum Output non deterministico per operazioni non associative o non commutativeNondeterministic output for nonassociative or noncommutative operations Output non deterministico per operazioni non associative o non commutativeNondeterministic output for nonassociative or noncommutative operations
Take Accetta i primi n elementiTakes first n elements Accetta n elementiTakes any n elements
TakeWhile Risultati ordinatiOrdered results Non deterministicoNondeterministic. Esegue TakeWhile sull'ordine arbitrario correntePerforms TakeWhile on the current arbitrary order
ThenBy Supplemento di OrderBySupplements OrderBy Supplemento di OrderBySupplements OrderBy
ThenByDescending Supplemento di OrderBySupplements OrderBy Supplemento di OrderBySupplements OrderBy
ToArray Risultati ordinatiOrdered results Risultati non ordinatiUnordered results
ToDictionary Non applicabileNot applicable Non applicabileNot applicable
ToList Risultati ordinatiOrdered results Risultati non ordinatiUnordered results
ToLookup Risultati ordinatiOrdered results Risultati non ordinatiUnordered results
Union Risultati ordinatiOrdered results Risultati non ordinatiUnordered results
Where Risultati ordinatiOrdered results Risultati non ordinatiUnordered results
Where (indicizzato)Where (indexed) Risultati ordinatiOrdered results Risultati non ordinatiUnordered results
Zip Risultati ordinatiOrdered results Risultati non ordinatiUnordered results

I risultati non ordinati non vengono disposti attivamente in ordine casuale, ma semplicemente non viene loro applicata alcuna logica speciale di ordinamento.Unordered results are not actively shuffled; they simply do not have any special ordering logic applied to them. In alcuni casi, una query non ordinata può mantenere l'ordine della sequenza di origine.In some cases, an unordered query may retain the ordering of the source sequence. Per le query che usano l'operatore Select indicizzato, PLINQ garantisce che gli elementi di output vengano restituiti nell'ordine crescente di indice, ma non viene in alcun modo garantito quali indici verranno assegnati a quali elementi.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.

Vedere ancheSee Also

Parallel LINQ (PLINQ)Parallel LINQ (PLINQ)
Programmazione parallelaParallel Programming