Compartir a través de


Cómo: Convertir un bucle OpenMP que usa una variable de reducción para usar el Runtime de simultaneidad

En este ejemplo se muestra cómo convertir un bucle OpenMP paralelopara que usa la cláusula reducción para emplear el Runtime de simultaneidad.

La cláusula OpenMP reduction permite especificar una o más variables privadas de subprocesos que están sujetas a una operación de reducción al final de la región paralela. OpenMP predefine un conjunto de operadores de reducción. Cada variable de reducción debe ser un escalar (por ejemplo, int, long y float). OpenMP también define varias restricciones sobre cómo se usan las variables de reducción en una región paralela.

La biblioteca de patrones de procesamiento paralelo (PPL) proporciona la clase concurrency::combinable, que proporciona un almacenamiento local de subprocesos reutilizable que permite realizar cálculos específicos y, a continuación, fusionar mediante combinación estos cálculos en un resultado final. La clase combinable es una plantilla que actúa en los tipos escalares y complejos. Para usar la clase combinable, realiza estos subcálculos en el cuerpo de una construcción paralela y, a continuación, llama al método concurrency::combinable::combine o concurrency::combinable::combine_each para generar el resultado final. Los métodos combine y combine_each toman una función de combinación que especifica cómo combinar cada par de elementos. Por consiguiente, la clase combinable no se limita a un conjunto fijo de operadores de reducción.

Ejemplo

En este ejemplo se usa OpenMP y el runtime de simultaneidad para calcular la suma de los 35 primeros números de 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 ejemplo produce el siguiente resultado:

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 más información sobre la clase combinable, consulte Contenedores y objetos paralelos.

Compilar el código

Copie el código de ejemplo y péguelo en un proyecto de Visual Studio o en un archivo denominado concrt-omp-fibonacci-reduction.cpp y, después, ejecute el siguiente comando en una ventana del símbolo del sistema de Visual Studio.

cl.exe /EHsc /openmp concrt-omp-fibonacci-reduction.cpp

Consulte también

Migración de OpenMP al Runtime de simultaneidad
Contenedores y objetos paralelos