Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En PLINQ, el objetivo es maximizar el rendimiento al tiempo que se mantiene la corrección. Una consulta debe ejecutarse lo más rápido posible, pero seguir produciendo los resultados correctos. En algunos casos, la corrección requiere que se conserve el orden de la secuencia de origen; sin embargo, la ordenación puede ser computacionalmente costosa. Por lo tanto, de forma predeterminada, PLINQ no conserva el orden de la secuencia de origen. En este sentido, PLINQ se parece a LINQ to SQL, pero es diferente de LINQ to Objects, que mantiene el orden.
Para anular la funcionalidad predeterminada, puede activar la preservación del orden mediante el operador AsOrdered en la secuencia de origen. Después, puede desactivar la conservación del orden más adelante en la consulta mediante el método AsUnordered. Con ambos métodos, la consulta se procesa en función de la heurística que determina si se debe ejecutar la consulta como paralela o como secuencial. Para obtener más información, consulte Comprender la aceleración en PLINQ.
En el ejemplo siguiente se muestra una consulta paralela desordenada que filtra todos los elementos que coinciden con una condición, sin intentar ordenar los resultados de ninguna manera.
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)
Esta consulta no produce necesariamente las primeras 1000 ciudades de la secuencia de origen que cumplen la condición, sino un conjunto de 1000 ciudades que cumplen la condición. Los operadores de consulta PLINQ dividen la secuencia de origen en varias subsecuencias que se procesan como tareas simultáneas. Si no se especifica la preservación del orden, los resultados de cada partición se transfieren a la siguiente etapa de la consulta en un orden arbitrario. Además, una partición puede producir un subconjunto de sus resultados antes de continuar procesando los elementos restantes. El orden resultante puede ser diferente cada vez. La aplicación no puede controlar esto porque depende de cómo programa el sistema operativo los subprocesos.
En el ejemplo siguiente se invalida el comportamiento predeterminado mediante el AsOrdered operador en la secuencia de origen. Esto garantiza que el Take método devuelva las primeras 1000 ciudades de la secuencia de origen que cumplen la condición.
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)
Sin embargo, esta consulta probablemente no se ejecute tan rápido como la versión desordenada porque debe realizar un seguimiento del orden original en todas las particiones y en el momento de la combinación asegurarse de que la ordenación sea coherente. Por lo tanto, se recomienda usar AsOrdered solo cuando sea necesario y solo para las partes de la consulta que lo requieran. Cuando la conservación del orden ya no sea necesaria, use AsUnordered para desactivarla. En el ejemplo siguiente se logra mediante la redacción de dos consultas.
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
Tenga en cuenta que PLINQ conserva la ordenación de una secuencia producida por operadores de imposición de orden para el resto de la consulta. Es decir, los operadores como OrderBy y ThenBy se tratan como si fueran seguidos de una llamada a AsOrdered.
Operadores de consulta y ordenación
Los siguientes operadores de consulta introducen la conservación del orden en todas las operaciones posteriores de una consulta o hasta que se llame a AsUnordered:
En algunos casos, los siguientes operadores de consulta PLINQ pueden requerir secuencias de origen ordenadas para generar resultados correctos:
Algunos operadores de consulta PLINQ se comportan de forma diferente, en función de si su secuencia de origen está ordenada o no ordenada. En la tabla siguiente se enumeran estos operadores.
Operador | Resultado cuando se ordena la secuencia de origen | Resultado cuando la secuencia de origen no está ordenada |
---|---|---|
Aggregate | Salida no determinista para operaciones no asociativas o no nomutantes | Salida no determinista para operaciones no asociativas o no nomutantes |
All | No aplicable | No aplicable |
Any | No aplicable | No aplicable |
AsEnumerable | No aplicable | No aplicable |
Average | Salida no determinista para operaciones no asociativas o no nomutantes | Salida no determinista para operaciones no asociativas o no nomutantes |
Cast | Resultados ordenados | Resultados desordenados |
Concat | Resultados ordenados | Resultados desordenados |
Count | No aplicable | No aplicable |
DefaultIfEmpty | No aplicable | No aplicable |
Distinct | Resultados ordenados | Resultados desordenados |
ElementAt | Devolver el elemento especificado | Elemento arbitrario |
ElementAtOrDefault | Devolver el elemento especificado | Elemento arbitrario |
Except | Resultados desordenados | Resultados desordenados |
First | Devolver el elemento especificado | Elemento arbitrario |
FirstOrDefault | Devolver el elemento especificado | Elemento arbitrario |
ForAll | Ejecuta de manera no determinista en paralelo | Ejecuta de manera no determinista en paralelo |
GroupBy | Resultados ordenados | Resultados desordenados |
GroupJoin | Resultados ordenados | Resultados desordenados |
Intersect | Resultados ordenados | Resultados desordenados |
Join | Resultados ordenados | Resultados desordenados |
Last | Devolver el elemento especificado | Elemento arbitrario |
LastOrDefault | Devolver el elemento especificado | Elemento arbitrario |
LongCount | No aplicable | No aplicable |
Min | No aplicable | No aplicable |
OrderBy | Reordena la secuencia | Inicia una nueva sección ordenada |
OrderByDescending | Reordena la secuencia | Inicia una nueva sección ordenada |
Range | No aplicable (el mismo valor predeterminado que AsParallel ) | No aplicable |
Repeat | No aplicable (el mismo valor predeterminado que AsParallel) | No aplicable |
Reverse | Invierte el orden | No hace nada |
Select | Resultados ordenados | Resultados desordenados |
Select (indexado) | Resultados ordenados | Resultados desordenados. |
SelectMany | Resultados ordenados. | Resultados desordenados |
SelectMany (indexado) | Resultados ordenados. | Resultados desordenados. |
SequenceEqual | Comparación ordenada | Comparación sin ordenar |
Single | No aplicable | No aplicable |
SingleOrDefault | No aplicable | No aplicable |
Skip | Omite los primeros n elementos | Omite los elementos n |
SkipWhile | Resultados ordenados. | No determinista. Ejecuta SkipWhile en el orden arbitrario actual |
Sum | Salida no determinista para operaciones no asociativas o no nomutantes | Salida no determinista para operaciones no asociativas o no nomutantes |
Take | Toma los n primeros elementos |
Toma cualquier elemento n |
TakeWhile | Resultados ordenados | No determinista. Ejecuta TakeWhile en el orden arbitrario actual |
ThenBy | Suplementos OrderBy |
Suplementos OrderBy |
ThenByDescending | Suplementos OrderBy |
Suplementos OrderBy |
ToArray | Resultados ordenados | Resultados desordenados |
ToDictionary | No aplicable | No aplicable |
ToList | Resultados ordenados | Resultados desordenados |
ToLookup | Resultados ordenados | Resultados desordenados |
Union | Resultados ordenados | Resultados desordenados |
Where | Resultados ordenados | Resultados desordenados |
Where (indexado) | Resultados ordenados | Resultados desordenados |
Zip | Resultados ordenados | Resultados desordenados |
Los resultados desordenados no se ordenan activamente; simplemente no tienen ninguna lógica de ordenación especial aplicada a ellos. En algunos casos, una consulta desordenada puede conservar la ordenación de la secuencia de origen. En el caso de las consultas que usan el operador Select indexado, PLINQ garantiza que los elementos de salida aparecerán en el orden de aumentar los índices, pero no garantiza qué índices se asignarán a qué elementos.