Compartilhar via


Aumento de velocidade de compreensão no PLINQ

O objetivo principal do PLINQ é acelerar a execução de LINQ to Objects consultas de executar os delegados de consulta em paralelo em computadores com vários núcleos. PLINQ melhor quando executa o processamento de cada elemento em uma coleção de origem é independente, com nenhum estado compartilhado envolvido entre os delegados individuais. Essas operações são comuns em LINQ to Objects e PLINQ e são chamadas de "delightfully paralela" porque eles prestam-se facilmente ao agendamento de vários segmentos. No entanto, nem todas as consultas consiste inteiramente em operações paralelas delightfully; Na maioria dos casos, uma consulta envolve alguns operadores ou não pode ser colocado em paralelo ou que lenta a execução paralela. E mesmo com consultas que são totalmente delightfully paralelas, PLINQ deve ainda a fonte de dados de partição agendar o trabalho em threads e normalmente os resultados de mesclagem quando a consulta for concluída. Todas essas operações é adicionar o custo computacional de paralelização; Esses custos de paralelização de inclusão são chamados de sobrecarga. Para atingir o desempenho ideal em uma consulta PLINQ, a meta é maximizar as partes que são delightfully em paralelas e minimizar as partes que exigem a sobrecarga. Este artigo fornece informações que irão ajudá-lo a escrever consultas PLINQ que são tão eficientes quanto possível enquanto ainda produzindo resultados corretos.

Fatores que consulta o PLINQ impacto no desempenho

As seções a seguir lista alguns dos fatores mais importantes que desempenho de consulta paralela de impacto. Estas são instruções gerais que, por si só, não são suficientes para prever o desempenho da consulta em todos os casos. Como sempre, é importante medir o desempenho real de consultas específicas em computadores com uma variedade de configurações de representantes e cargas.

  1. Custo computacional geral do trabalho.

    Para obter um aumento de velocidade, uma consulta PLINQ deve ter suficiente delightfully paralelo trabalho a sobrecarga de deslocamento. O trabalho pode ser expresso como o custo computacional de cada delegado multiplicado pelo número de elementos na coleção de origem. Supondo que uma operação pode ser colocado em paralelo, mais computacionalmente caro é, quanto maior a oportunidade de aumento de velocidade. Por exemplo, se uma função usa um milissegundo para executar, uma consulta seqüencial mais de mil elementos levará um segundo para executar esta operação enquanto um paralelo de consulta em um computador com quatro núcleos pode levar apenas 250 milissegundos. Isso produz um aumento de velocidade de 750 milissegundos. Se a função necessária executar para cada elemento de um segundo, o aumento de velocidade seria 750 segundos. Se o delegado é muito caro, o PLINQ pode oferecer um aumento de velocidade significativo com apenas alguns itens na coleção de origem. Por outro lado, coleções de fonte pequeno com delegados triviais geralmente não são bons candidatos para PLINQ.

    No exemplo a seguir, queryA é provavelmente um bom candidato para PLINQ, supondo que a função Select thatits envolve muito trabalho. queryB provavelmente não é uma boa opção porque não é suficiente trabalho na instrução Select, e a sobrecarga da paralelização serão deslocadas a maior parte ou todo o aumento de velocidade.

    Dim queryA = From num In numberList.AsParallel()
                 Select ExpensiveFunction(num); 'good for PLINQ
    
    Dim queryB = From num In numberList.AsParallel()
                 Where num Mod 2 > 0
                 Select num; 'not as good for PLINQ
    
    var queryA = from num in numberList.AsParallel()
                 select ExpensiveFunction(num); //good for PLINQ
    
    var queryB = from num in numberList.AsParallel()
                 where num % 2 > 0
                 select num; //not as good for PLINQ
    
  2. O número de núcleos lógicos no sistema (grau de paralelismo).

    Esse ponto é um resultado óbvio para a seção anterior, as consultas são delightfully paralelas executados mais rapidamente em máquinas com mais núcleos porque o trabalho pode ser dividido entre segmentos simultâneos mais. A quantidade total do aumento de velocidade depende de qual é a porcentagem geral do trabalho da consulta é parallelizable. No entanto, não assuma que todas as consultas serão executado duas vezes mais rápida em um computador com oito principais como um computador de quatro principais. Quando o ajuste de consultas para um desempenho ideal, é importante medir os resultados reais em computadores com vários números de núcleos. Este ponto está relacionado ao ponto de n º 1: conjuntos de dados maiores são necessárias para tirar proveito dos recursos de computação maiores.

  3. O número e o tipo de operações.

    PLINQ fornece o operador de AsOrdered para situações em que é necessário para manter a ordem dos elementos na seqüência de origem. Há um custo associado à ordenação, mas esse custo é geralmente modesto. Operações GroupBy e Join da mesma forma incorrer em sobrecarga. PLINQ funciona melhor quando é permitido para processar os elementos na coleção de origem em qualquer ordem e passá-las ao próximo operador assim que elas estiverem prontas. Para obter mais informações, consulte Preservação da ordem PLINQ.

  4. O formulário de execução da consulta.

    Se você estiver armazenando os resultados de uma consulta chamando ToArray ou ToList, os resultados de todos os segmentos paralelos devem ser mesclados na estrutura de dados único. Isso envolve um custo computacional inevitável. Da mesma forma, se você iterar os resultados usando um loop foreach (For Each em Visual Basic), os resultados de threads de trabalho precisam ser serializado no thread enumerador. Mas se você desejar apenas executar alguma ação com base no resultado de cada thread, você pode usar o método ForAll para realizar esse trabalho em vários segmentos.

  5. O tipo de opções de mesclagem.

    Pode ser configurado o PLINQ sua saída de buffer e produzi-las em blocos ou todos ao mesmo tempo, depois que o conjunto de resultados inteiro é produzido, ou outra resultados individuais de fluxo como eles são produzidos. O primeiro resultado é reduzido tempo de execução geral e os resultados da última na menor latência entre elementos yielded. Enquanto as opções de mesclagem não tem sempre um grande impacto no desempenho geral da consulta, que possam afetar o desempenho observado porque eles controlam quanto tempo um usuário deve aguardar para ver os resultados. Para obter mais informações, consulte Mesclar as opções de PLINQ.

  6. O tipo de particionamento.

    Em alguns casos, uma consulta PLINQ através de uma coleção de origem indexáveis pode resultar em uma carga de trabalho desbalanceado. Quando isso ocorrer, talvez você possa aumentar o desempenho da consulta, criando um partitioner personalizado. Para obter mais informações, consulte Partitioners personalizados para PLINQ e TPL.

Quando o PLINQ escolhe o modo seqüencial

O PLINQ sempre tentará executar uma consulta pelo menos tão rápida quanto a consulta seria executada seqüencialmente. Embora PLINQ não observar como computacionalmente caro os representantes de usuário são ou como a fonte de entrada é o tamanho, procure em determinada consulta "formas". Especificamente, ele procura os operadores de consulta ou combinações de operadores que geralmente causam uma consulta executar mais lentamente no modo paralelo. Ao encontrar tais formas, por padrão, o PLINQ volta para o modo seqüencial.

No entanto, depois de medir o desempenho de uma consulta específica, você pode determinar que ele é realmente executado mais rapidamente no modo paralelo. Em tais casos, você pode usar o ParallelExecutionMode.ForceParallelism sinalizar o ParallelEnumerableWithExecutionMode() método para instruir o PLINQ paralelizar consulta. Para obter mais informações, consulte Como: Especificar o modo de execução no PLINQ.

A lista a seguir descreve as formas de consulta PLINQ por padrão será executado no modo seqüencial:

  • Consultas que contêm um Select, Where, indexado SelectMany indexado, ou cláusula de ElementAt após um operador de classificação ou filtragem removidos ou reorganizados índices originais.

  • Consultas que contêm um ignorar Take, TakeWhile, o operador de SkipWhile e onde os índices na seqüência de origem não estão na ordem original.

  • Consultas que contêm o Zip ou SequenceEquals, a menos que uma das fontes de dados tem um índice solicitado originalmente e fonte de dados (ou seja, é indexável uma matriz ou IList(T)).

  • Consultas que contêm Concat, a menos que ela é aplicada a fontes de dados indexáveis.

  • Consultas que contêm o inverso, a menos que aplicado a uma fonte de dados indexáveis.

Consulte também

Conceitos

Parallel LINQ PLINQ)