Compartilhar via


Algoritmos paralelos

O paralela padrões PPL (biblioteca) fornece os algoritmos que realizam simultaneamente o trabalho em coleções de dados. Esses algoritmos são semelhantes aos fornecidos pelo modelo Biblioteca STL (Standard).

Os algoritmos paralelos são compostos de funções existentes no Runtime de simultaneidade. Por exemplo, o Concurrency::parallel_for algoritmo usa uma Concurrency::structured_task_group objeto para realizar as iterações do loop paralelo. O parallel_for partições do algoritmo trabalham de maneira ideal, dada o número disponível de recursos de computação.

Seções

Este tópico descreve os seguintes algoritmos paralelos em detalhes:

  • Algoritmo de parallel_for

  • Algoritmo de parallel_for_each

  • Algoritmo de parallel_invoke

Algoritmo de parallel_for

O Concurrency::parallel_for repetidamente, o algoritmo realiza a mesma tarefa em paralelo. Cada uma dessas tarefas é parametrizada por um valor de iteração. Esse algoritmo é útil quando você tem um corpo de loop não compartilhar recursos entre as iterações do loop.

O parallel_for tarefas de partições do algoritmo de maneira ideal para execução paralela. Ele usa um algoritmo de roubo de trabalho para equilibrar a essas partições, cargas de trabalho são desbalanceadas. Quando uma iteração de loop bloqueia de forma cooperativa, o runtime redistribui o intervalo de iterações que é atribuído ao segmento atual para outros segmentos ou processadores. Da mesma forma, quando um thread conclui um intervalo de iterações, o runtime redistribui o trabalho de outros segmentos para esse segmento. O parallel_for também suporta um algoritmo aninhado paralelismo. Quando um loop paralelo contém outro loop paralelo, o runtime coordena os recursos de processamento entre os corpos de loop de maneira eficiente para execução em paralelo.

O parallel_for algoritmo tem duas versões sobrecarregadas. A primeira versão leva a uma função de trabalho (uma expressão lambda, o objeto de função ou o ponteiro de função), um valor final e um valor inicial. A segunda versão tem um valor inicial, um valor final, um valor pelo qual etapa e uma função de trabalho. A primeira versão dessa função usa 1 como o valor de etapa.

Você pode converter muitos for loops para usar parallel_for. No entanto, o parallel_for difere do algoritmo de for instrução das seguintes maneiras:

  • O parallel_for algoritmo parallel_for não executar as tarefas em uma ordem predeterminada.

  • O parallel_for não oferece suporte ao algoritmo de condições de terminação arbitrária. O parallel_for algoritmo pára quando o valor atual da variável de iteração é menor do que _Last.

  • O _Index_type o parâmetro de tipo deve ser um tipo integral. Esse tipo de integral pode ser assinado ou não assinado.

  • A iteração de loop deve ser em frente. O parallel_for algoritmo lança uma exceção do tipo std::invalid_argument se a _Step parâmetro é menor que 1.

  • O mecanismo de tratamento de exceção para o parallel_for algoritmo difere de um for loop. Se várias exceções ocorrem simultaneamente em um corpo do loop paralelo, o runtime propaga apenas uma das exceções para o thread que chamou parallel_for. Além disso, quando uma iteração do loop lança uma exceção, o tempo de execução não parar imediatamente o loop geral. Em vez disso, o loop é colocado no estado cancelado e o tempo de execução descarta todas as tarefas que ainda não iniciaram. Para obter mais informações sobre os algoritmos paralelos e de manipulação de exceção, consulte O Runtime de simultaneidade de manipulação de exceção.

Embora o parallel_for algoritmo não oferece suporte a condições de terminação arbitrário, você pode usar o cancelamento para parar todas as tarefas. Para obter mais informações sobre o cancelamento, consulte Cancelamento na PPL.

ObservaçãoObservação

O custo de agendamento que resultados de balanceamento de carga e o suporte para recursos como o cancelamento não podem superar os benefícios de executar o corpo do loop em paralelo, especialmente quando o corpo do loop é relativamente pequeno.

Exemplo

O exemplo a seguir mostra a estrutura básica da parallel_for algoritmo. Este exemplo imprime no console de cada valor no intervalo [1, 5] em paralelo.

// parallel-for-structure.cpp
// compile with: /EHsc
#include <ppl.h>
#include <array>
#include <sstream>
#include <iostream>

using namespace Concurrency;
using namespace std;

int wmain()
{
   // Print each value from 1 to 5 in parallel.
   parallel_for(1, 6, [](int value) {
      wstringstream ss;
      ss << value << L' ';
      wcout << ss.str();
   });
}

Este exemplo produz a saída de exemplo a seguir:

1 2 4 3 5

Porque o parallel_for algoritmo atua em cada item em paralelo, a ordem na qual os valores são impressas no console irá variar.

Para obter um exemplo completo que usa o parallel_for o algoritmo, consulte Como: Escrever um Loop de parallel_for.

go to top

Algoritmo de parallel_for_each

O Concurrency::parallel_for_each algoritmo realiza tarefas em um contêiner iterativo, tais como aqueles fornecidos pela STL, em paralelo. Ele usa a mesma lógica de particionamento que o parallel_for algoritmo usa.

O parallel_for_each algoritmo semelhante a STL std::for_each o algoritmo, exceto que o parallel_for_each algoritmo executa as tarefas simultaneamente. Como outros algoritmos paralelos, parallel_for_each não executar as tarefas em uma ordem específica.

Embora o parallel_for_each algoritmo funciona iteradores direta e iteradores de acesso aleatório, realiza melhor com acesso aleatório iteradores.

Exemplo

O exemplo a seguir mostra a estrutura básica da parallel_for_each algoritmo. Este exemplo imprime o console de cada valor em um std::array o objeto em paralelo.

// parallel-for-each-structure.cpp
// compile with: /EHsc
#include <ppl.h>
#include <array>
#include <sstream>
#include <iostream>

using namespace Concurrency;
using namespace std;

int wmain()
{
   // Create an array of integer values.
   array<int, 5> values = { 1, 2, 3, 4, 5 };

   // Print each value in the array in parallel.
   parallel_for_each(values.begin(), values.end(), [](int value) {
      wstringstream ss;
      ss << value << L' ';
      wcout << ss.str();
   });
}

Este exemplo produz a saída de exemplo a seguir:

4 5 1 2 3

Porque o parallel_for_each algoritmo atua em cada item em paralelo, a ordem na qual os valores são impressas no console irá variar.

Para obter um exemplo completo que usa o parallel_for_each o algoritmo, consulte Como: Escrever um Loop de parallel_for_each.

go to top

Algoritmo de parallel_invoke

O Concurrency::parallel_invoke algoritmo executa um conjunto de tarefas em paralelo. Ele não retorna até termina de cada tarefa. Esse algoritmo é útil quando você tem várias tarefas independentes que você deseja executar ao mesmo tempo.

O parallel_invoke algoritmo assume como seus parâmetros de uma série de funções de trabalho (funções de lambda, objetos de função ou ponteiros de função). O parallel_invoke algoritmo está sobrecarregado para levar entre dois e dez parâmetros. Cada função que você passa para parallel_invoke deve levar zero parâmetros.

Como outros algoritmos paralelos, parallel_invoke não executar as tarefas em uma ordem específica. O tópico Paralelismo de tarefas (Runtime de simultaneidade) explica como o parallel_invoke algoritmo está relacionado a tarefas e grupos de tarefas.

Exemplo

O exemplo a seguir mostra a estrutura básica da parallel_invoke algoritmo. Este exemplo simultaneamente chama o twice função de três variáveis locais e imprime o resultado no console.

// parallel-invoke-structure.cpp
// compile with: /EHsc
#include <ppl.h>
#include <string>
#include <iostream>

using namespace Concurrency;
using namespace std;

// Returns the result of adding a value to itself.
template <typename T>
T twice(const T& t) {
   return t + t;
}

int wmain()
{
   // Define several values.
   int n = 54;
   double d = 5.6;
   wstring s = L"Hello";

   // Call the twice function on each value concurrently.
   parallel_invoke(
      [&n] { n = twice(n); },
      [&d] { d = twice(d); },
      [&s] { s = twice(s); }
   );

   // Print the values to the console.
   wcout << n << L' ' << d << L' ' << s << endl;
}

Esse exemplo produz a seguinte saída.

108 11.2 HelloHello

Para obter exemplos completos que usam o parallel_invoke o algoritmo, consulte Como: Use o parallel_invoke para escrever uma rotina de classificação paralela e Como: Use o parallel_invoke para executar operações paralelas.

go to top

Tópicos relacionados

Referência

Função de parallel_for

Função de parallel_for_each

Função de parallel_invoke