Opções de mesclagem no PLINQ
Quando uma consulta é executada em paralelo, o PLINQ particiona a sequência de origem para que vários threads possam trabalhar em diferentes partes simultaneamente, normalmente em threads separados. Se os resultados devem ser consumidos em um thread, por exemplo, em um foreach
loop (For Each
no Visual Basic), então os resultados de cada thread devem ser mesclados de volta em uma sequência. O tipo de mesclagem que PLINQ executa depende dos operadores que estão presentes na consulta. Por exemplo, os operadores que impõem uma nova ordem nos resultados devem armazenar em buffer todos os elementos de todos os threads. Da perspetiva do thread de consumo (que também é o do usuário do aplicativo), uma consulta totalmente armazenada em buffer pode ser executada por um período de tempo percetível antes de produzir seu primeiro resultado. Outros operadores, por padrão, são parcialmente armazenados em buffer; eles produzem seus resultados em lotes. Um operador, ForAll não é armazenado em buffer por padrão. Ele produz todos os elementos de todos os threads imediatamente.
Usando o WithMergeOptions método, como 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 suportar a opção solicitada, a opção será simplesmente ignorada. Na maioria dos casos, não é necessário especificar uma opção de mesclagem para uma consulta PLINQ. No entanto, em alguns casos, você pode descobrir, 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 de usuário mais responsiva.
ParallelMergeOptions
A ParallelMergeOptions enumeração inclui as seguintes opções que especificam, para formas de consulta suportadas, como a saída final da consulta é produzida 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 é produzido. Esse comportamento é análogo ao "streaming" da saída. Se o AsOrdered operador estiver presente na consulta,
NotBuffered
preserva a ordem dos elementos de origem. EmboraNotBuffered
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 AutoBuffered opção faz com que a consulta colete elementos em um buffer e, em seguida, produza periodicamente o conteúdo do buffer de uma só vez para o thread consumidor. Isso é análogo a produzir os dados de origem em "partes" em vez de usar o comportamento de "streaming" do
NotBuffered
.AutoBuffered
pode levar mais tempo do queNotBuffered
disponibilizar o primeiro elemento no thread de consumo. O tamanho do buffer e o comportamento exato de produção 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 produzido. 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 suportam opções de mesclagem
A tabela a seguir lista os operadores que suportam todos os modos de opção de mesclagem, sujeitos às restrições especificadas.
Operador | Restrições |
---|---|
AsEnumerable | Nenhuma |
Cast | Nenhuma |
Concat | Consultas não ordenadas que têm apenas uma fonte Array ou List. |
DefaultIfEmpty | Nenhuma |
OfType | Nenhuma |
Reverse | Consultas não ordenadas que têm apenas uma fonte Array ou List. |
Select | Nenhuma |
SelectMany | None |
Skip | None |
Take | None |
Where | Nenhuma |
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 nenhum elemento 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 manipular 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 , cede seus elementos imediatamente. OrderBy é sempre FullyBuffered, deve ordenar toda a lista antes de ceder.