Como converter um loop OpenMP que usa uma variável de redução para usar o runtime de simultaneidade
Este exemplo demonstra como converter um loop parallelfor OpenMP que usa a cláusula reduction para usar o Runtime de Simultaneidade.
A cláusula reduction
OpenMP permite especificar uma ou mais variáveis thread-private sujeitas a uma operação de redução no final da região paralela. O OpenMP predefine um conjunto de operadores de redução. Cada variável de redução deve ser escalar (por exemplo, int
, long
e float
). O OpenMP também define várias restrições sobre como as variáveis de redução são usadas em uma região paralela.
A PPL (Parallel Patterns Library) fornece a classe concurrency::combinable , que fornece armazenamento local de thread reutilizável que permite executar cálculos refinados e então mesclar essas computações em um resultado final. A classe combinable
é um modelo que atua em tipos escalares e complexos. Para usar a classe combinable
, execute sub computações no corpo de um constructo paralelo e chame o método concurrency::combinable::combine ou concurrency::combinable::combine_each para produzir o resultado final. Os métodos combine
e combine_each
usam uma função de combinação que especifica como combinar cada par de elementos. Portanto, a classe combinable
não está restrita a um conjunto fixo de operadores de redução.
Exemplo
Este exemplo usa o OpenMP e o Runtime de Simultaneidade para computar a soma dos 35 primeiros números Fibonacci.
// concrt-omp-fibonacci-reduction.cpp
// compile with: /EHsc /openmp
#include <ppl.h>
#include <iostream>
using namespace concurrency;
using namespace std;
// Computes the nth Fibonacci number.
// This function illustrates a lengthy operation and is therefore
// not optimized for performance.
int fibonacci(int n)
{
if (n < 2)
return n;
// Compute the components in parallel.
int n1, n2;
parallel_invoke(
[n,&n1] { n1 = fibonacci(n-1); },
[n,&n2] { n2 = fibonacci(n-2); }
);
return n1 + n2;
}
// Uses OpenMP to compute the sum of Fibonacci numbers in parallel.
void omp_parallel_fibonacci_sum(int count)
{
int sum = 0;
#pragma omp parallel for reduction(+ : sum)
for (int i = 0; i < count; ++i)
{
sum += fibonacci(i);
}
wcout << L"The sum of the first " << count << L" Fibonacci numbers is "
<< sum << L'.' << endl;
}
// Uses the Concurrency Runtime to compute the sum of Fibonacci numbers in parallel.
void concrt_parallel_fibonacci_sum(int count)
{
combinable<int> sums;
parallel_for(0, count, [&sums](int i)
{
sums.local() += fibonacci(i);
});
wcout << L"The sum of the first " << count << L" Fibonacci numbers is "
<< sums.combine(plus<int>()) << L'.' << endl;
}
int wmain()
{
const int count = 35;
wcout << L"Using OpenMP..." << endl;
omp_parallel_fibonacci_sum(count);
wcout << L"Using the Concurrency Runtime..." << endl;
concrt_parallel_fibonacci_sum(count);
}
Este exemplo gerencia a seguinte saída.
Using OpenMP...
The sum of the first 35 Fibonacci numbers is 14930351.
Using the Concurrency Runtime...
The sum of the first 35 Fibonacci numbers is 14930351.
Para mais informações sobre a classe combinable
, confira Contêineres e objetos paralelos.
Compilando o código
Copie o código de exemplo e cole-o em um projeto do Visual Studio, ou cole-o em um arquivo chamado concrt-omp-fibonacci-reduction.cpp
e execute o comando a seguir em uma janela do Prompt de comando do Visual Studio.
cl.exe /EHsc /openmp concrt-omp-fibonacci-reduction.cpp
Confira também
Migrando do OpenMP para o runtime de simultaneidade
Contêineres e objetos em paralelo