Opciones de fusión mediante combinación en PLINQ

Cuando una consulta se ejecuta en paralelo, PLINQ crea particiones de la secuencia de origen para que varios subprocesos puedan funcionar en diferentes partes al mismo tiempo, por lo general en subprocesos independientes. Si los resultados se van a usar en un subproceso, por ejemplo, en un bucle foreach (For Each en Visual Basic), los resultados de cada subproceso deben volver a combinarse en una secuencia. El tipo de combinación que PLINQ realiza depende de los operadores que están presentes en la consulta. Por ejemplo, los operadores que imponen un nuevo orden de los resultados deben almacenar en búfer todos los elementos de todos los subprocesos. Desde la perspectiva del subproceso utilizado (que también es el del usuario de la aplicación), una consulta totalmente almacenada en búfer podría ejecutarse durante un período de tiempo considerable antes de generar su primer resultado. Otros operadores, de forma predeterminada, están parcialmente almacenados en búfer; producen sus resultados en lotes. Un operador, ForAll, no se almacena en búfer de forma predeterminada. Genera inmediatamente todos los elementos de todos los subprocesos.

Mediante el uso del método WithMergeOptions, como se muestra en el ejemplo siguiente, puede proporcionar una sugerencia a PLINQ que indica qué tipo de combinación se debe llevar a cabo.

var scanLines = from n in nums.AsParallel()
                    .WithMergeOptions(ParallelMergeOptions.NotBuffered)
                where n % 2 == 0
                select ExpensiveFunc(n);
Dim scanlines = From n In nums.AsParallel().WithMergeOptions(ParallelMergeOptions.NotBuffered)
                Where n Mod 2 = 0
                Select ExpensiveFunc(n)

Para obtener el ejemplo completo, vea Cómo: Especificar opciones de fusión mediante combinación en PLINQ.

Si la consulta determinada no puede admitir la opción solicitada, simplemente se omitirá la opción. En la mayoría de los casos, no es necesario especificar una opción de combinación para una consulta PLINQ. Sin embargo, en algunos casos puede observar mediante pruebas y mediciones que una consulta se ejecuta mejor en un modo no predeterminado. Un uso común de esta opción es forzar a un operador de combinación de fragmentos a transmitir por secuencias sus resultados con el fin de proporcionar una interfaz de usuario más dinámica.

ParallelMergeOptions

La enumeración ParallelMergeOptions incluye las siguientes opciones que especifican, para las formas de consulta compatibles, cómo se produjo el resultado final de la consulta cuando se usan los resultados en un subproceso:

  • Not Buffered

    La opción NotBuffered hace que cada elemento procesado devuelva cada subproceso en cuanto se produzca. Este comportamiento es análogo a la salida "streaming". Si el operador AsOrdered está presente en la consulta, NotBuffered conserva el orden de los elementos de origen. Aunque NotBuffered empieza a producir resultados en cuanto están disponibles, el tiempo total para generar todos los resultados puede ser más largo con respecto al uso de alguna de las demás opciones de combinación.

  • Auto Buffered

    La opción AutoBuffered hace que la consulta recopile los elementos en un búfer y, a continuación, proporcionará periódicamente el contenido del búfer a la vez para el subproceso utilizado. Esto es análogo a producir los datos de origen en "fragmentos" en lugar de usar el comportamiento de "streaming" de NotBuffered. AutoBuffered puede tardar más que NotBuffered en habilitar el primer elemento en el subproceso utilizado. El tamaño del búfer y el comportamiento productivo exacto no se pueden configurar y pueden variar en función de varios factores relacionados con la consulta.

  • FullyBuffered

    La opción FullyBuffered hace que el resultado de la consulta completa se almacene en búfer antes de que se produzca cualquiera de los elementos. Al usar esta opción, puede tardar más tiempo antes de que el primer elemento esté disponible en el subproceso utilizado, pero los resultados completos pueden producirse más rápido en comparación con el uso de otras opciones.

Operadores de consulta que admiten opciones de combinación

En la tabla siguiente se enumeran los operadores que admiten todos los modos de opción de combinación, sujetos a las restricciones especificadas.

Operador Restricciones
AsEnumerable None
Cast None
Concat Consultas no ordenadas que tienen solo un origen de matriz o lista.
DefaultIfEmpty None
OfType None
Reverse Consultas no ordenadas que tienen solo un origen de matriz o lista.
Select None
SelectMany None
Skip None
Take None
Where None

Todos los demás operadores de consulta PLINQ podrían omitir opciones de combinación proporcionadas por el usuario. Algunos operadores de consulta, por ejemplo Reverse y OrderBy, no pueden proporcionar todos los elementos hasta que no se hayan producido y reordenado. Por lo tanto, cuando se utiliza ParallelMergeOptions en una consulta que también contiene un operador como Reverse, el comportamiento de combinación no se aplicará en la consulta hasta después de que el operador genere sus resultados.

La capacidad de algunos operadores para controlar las opciones de combinación depende del tipo de la secuencia de origen y de si el operador AsOrdered se usó anteriormente en la consulta. ForAll siempre es NotBuffered; produce inmediatamente sus elementos. OrderBy siempre es FullyBuffered; debe ordenar toda la lista antes de producirla.

Vea también