Partager via


Comment : convertir une boucle OpenMP qui a recours à une variable de réduction pour utiliser le runtime d'accès concurrentiel

Cet exemple montre comment convertir une boucle parallel for OpenMP qui utilise la clause reduction pour utiliser le runtime d'accès concurrentiel.

La clause reduction OpenMP vous permet de spécifier une ou plusieurs variables de thread privé qui sont soumises à une opération de réduction à la fin de la zone parallèle. OpenMP prédéfinit un ensemble d'opérateurs de réduction. Chaque variable de réduction doit être une variable scalaire (par exemple, int, long et float). OpenMP définit également plusieurs restrictions sur la façon dont les variables de réduction sont utilisées dans la région parallèle.

La bibliothèque de modèles parallèles (PPL) fournit la classe concurrency::combinable, qui fournit un stockage local des threads réutilisable qui vous permet d'effectuer des calculs affinés, puis de fusionner ces calculs dans un résultat final. La classe combinable est un modèle qui agit sur les types scalaires et les types complexes. Pour utiliser la classe combinable, exécutez les sous-calculs dans le corps d'un élément parallèle, puis appelez la méthode concurrency::combinable::combine ou concurrency::combinable::combine_each pour produire le résultat final. Les méthodes combine et combine_each prennent chacune une fonction de combinaison qui spécifie comment combiner chaque paire d'éléments. Par conséquent, la classe combinable ne se limite pas à un ensemble fixe d'opérateurs de réduction.

Exemple

Cet exemple utilise OpenMP et le runtime d'accès concurrentiel pour calculer la somme des 35 premiers nombres 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);
}

Cet exemple génère la sortie suivante.

  

Pour plus d'informations sur la classe combinable, consultez Conteneurs et objets parallèles.

Compilation du code

Copiez l'exemple de code et collez-le dans un projet Visual Studio, ou collez-le dans un fichier nommé concrt-omp-fibonacci-reduction.cpp. Exécutez ensuite la commande suivante dans une fenêtre d'invite de commandes Visual Studio.

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

Voir aussi

Concepts

Migration d'OpenMP au runtime d'accès concurrentiel

Conteneurs et objets parallèles