Condividi tramite


Procedura: convertire un ciclo OpenMP che utilizza una variabile di riduzione per l'utilizzo del runtime di concorrenza

In questo esempio viene illustrato come convertire un ciclo parallel for di OpenMP che utilizza la clausola reduction per utilizzare il runtime di concorrenza.

La clausola reduction di OpenMP consente di specificare una o più variabili thread-private che sono soggette a un'operazione di riduzione alla fine dell'area parallela. OpenMP predefinisce un set di operatori di riduzione. Ogni variabile di riduzione deve essere scalare, ad esempio int, long e float. OpenMP definisce inoltre diverse restrizioni sull'utilizzo delle variabili di riduzione in un'area parallela.

La libreria PPL (Parallel Patterns Library) fornisce la classe Concurrency::combinable, la quale fornisce l'archiviazione locale dei thread riutilizzabile che consente di eseguire calcoli con granularità fine e quindi di unire tali calcoli in un risultato finale. La classe combinable è un modello che agisce sia sui tipi scalari che sui tipi complessi. Per utilizzare la classe combinable, eseguire i sotto-calcoli nel corpo di un costrutto parallelo e quindi chiamare il metodo Concurrency::combinable::combine o Concurrency::combinable::combine_each per fornire il risultato finale. I metodi combine e combine_each accettano ciascuno una funzione combine che specifica come combinare ogni coppia di elementi. La classe combinable non è pertanto limitata a un set prestabilito di operatori di riduzione.

Esempio

In questo esempio vengono utilizzati sia OpenMP che il runtime di concorrenza per calcolare la somma dei primi 35 numeri di 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);
}

Questo esempio produce l'output che segue.

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.

Per ulteriori informazioni sulla classe combinable, vedere Contenitori e oggetti paralleli.

Compilazione del codice

Copiare il codice di esempio e incollarlo in un progetto Visual Studio oppure incollarlo in un file denominato concrt-omp-fibonacci-reduction.cpp, quindi eseguire il comando seguente in una finestra del prompt dei comandi di Visual Studio 2010.

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

Vedere anche

Concetti

Contenitori e oggetti paralleli

Altre risorse

Migrazione da OpenMP al runtime di concorrenza