Compartilhar via


Opções de mesclagem no PLINQ

Quando uma consulta está sendo executada como paralela, o PLINQ particiona a sequência de origem para que vários threads possam funcionar simultaneamente em diferentes partes, normalmente em threads separados. Se os resultados forem consumidos em um thread, por exemplo, em um foreach loop (For Each no Visual Basic), os resultados de cada thread deverão ser mesclados novamente em uma sequência. O tipo de mesclagem executada pelo PLINQ depende dos operadores presentes na consulta. Por exemplo, os operadores que impõem uma nova ordem sobre os resultados devem armazenar em buffer todos os elementos de todos os threads. Do ponto de vista do thread de consumo (que também é o thread do usuário do aplicativo), uma consulta totalmente armazenada em buffer pode ser executada por um período significativo de tempo antes de produzir seu primeiro resultado. Por padrão, outros operadores são parcialmente armazenados em buffer e geram seus resultados em lotes. Um operador ForAll não é armazenado em buffer por padrão. Ele gera todos os elementos de todos os threads imediatamente.

Usando o WithMergeOptions método, conforme mostrado no exemplo a seguir, você pode fornecer uma dica para PLINQ que indica que tipo de mesclagem executar.

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 obter o exemplo completo, consulte Como especificar opções de mesclagem no PLINQ.

Se a consulta específica não puder dar suporte à opção solicitada, a opção será ignorada. Na maioria dos casos, você não precisa especificar uma opção de mesclagem para uma consulta PLINQ. No entanto, em alguns casos, você pode encontrar testando e medindo que uma consulta é executada melhor em um modo não padrão. Um uso comum dessa opção é forçar um operador de mesclagem de partes a transmitir seus resultados para fornecer uma interface do usuário mais responsiva.

ParallelMergeOptions

A ParallelMergeOptions enumeração inclui as seguintes opções que especificam, para formas de consulta com suporte, como a saída final da consulta é gerada quando os resultados são consumidos em um thread:

  • Not Buffered

    A NotBuffered opção faz com que cada elemento processado seja retornado de cada thread assim que ele é produzido. Esse comportamento é análogo a "transmitir" a saída. Se o AsOrdered operador estiver presente na consulta, NotBuffered preservará a ordem dos elementos de origem. Embora NotBuffered comece a produzir resultados assim que eles estiverem disponíveis, o tempo total para produzir todos os resultados ainda pode ser maior do que usar uma das outras opções de mesclagem.

  • Auto Buffered

    A opção AutoBuffered faz com que a consulta colete elementos em um buffer e, em seguida, ceda periodicamente todo o conteúdo do buffer de uma vez para a thread consumidora. Isso equivale a gerar os dados de origem em "partes" em vez de usar o comportamento de "streaming" de NotBuffered. AutoBuffered pode levar mais tempo do que NotBuffered para disponibilizar o primeiro elemento no thread de consumo. O tamanho do buffer e o comportamento exato de rendimento não são configuráveis e podem variar, dependendo de vários fatores relacionados à consulta.

  • FullyBuffered

    A FullyBuffered opção faz com que a saída de toda a consulta seja armazenada em buffer antes que qualquer um dos elementos seja gerado. Quando você usa essa opção, pode levar mais tempo até que o primeiro elemento esteja disponível no thread de consumo, mas os resultados completos ainda podem ser produzidos mais rapidamente do que usando as outras opções.

Operadores de consulta que dão suporte a opções de mesclagem

A tabela a seguir lista os operadores que dão suporte a todos os modos de opção de mesclagem, sujeitos às restrições especificadas.

Operador Restrições
AsEnumerable Nenhum
Cast Nenhum
Concat Consultas não ordenadas que têm apenas uma matriz ou fonte de lista.
DefaultIfEmpty Nenhum
OfType Nenhum
Reverse Consultas não ordenadas que têm apenas uma matriz ou fonte de lista.
Select Nenhum
SelectMany Nenhum
Skip Nenhum
Take Nenhum
Where Nenhum

Todos os outros operadores de consulta PLINQ podem ignorar as opções de mesclagem fornecidas pelo usuário. Alguns operadores de consulta, por exemplo, Reverse e OrderBy, não podem produzir elementos até que todos tenham sido produzidos e reordenados. Portanto, quando ParallelMergeOptions é usado em uma consulta que também contém um operador como Reverse, o comportamento de mesclagem não será aplicado na consulta até que esse operador tenha produzido seus resultados.

A capacidade de alguns operadores de lidar com opções de mesclagem depende do tipo da sequência de origem e se o AsOrdered operador foi usado anteriormente na consulta. ForAll é sempre NotBuffered; ele suspende seus elementos imediatamente. OrderBy é sempre FullyBuffered; ele precisa classificar a lista inteira antes de suspendê-la.

Consulte também