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 un parallèleOpenMP pour la boucle qui utilise la clause de réduction pour utiliser le runtime d’accès concurrentiel.

La clause OpenMP reduction vous permet de spécifier une ou plusieurs variables privées de thread soumises à une opération de réduction à la fin de la région parallèle. OpenMP prédéfini un ensemble d’opérateurs de réduction. Chaque variable de réduction doit être scalaire (par exemple, int, longet float). OpenMP définit également plusieurs restrictions sur l’utilisation des variables de réduction dans une région parallèle.

La bibliothèque de modèles parallèles (PPL) fournit la classe concurrency ::combinable , qui fournit un stockage réutilisable, thread-local qui vous permet d’effectuer des calculs affinés, puis de fusionner ces calculs dans un résultat final. La combinable classe est un modèle qui agit à la fois sur des types scalaires et complexes. Pour utiliser la combinable classe, effectuez des sous-calculs dans le corps d’une construction parallèle, puis appelez la méthode concurrency ::combinable ::combine ou concurrency ::combinable ::combine_each pour produire le résultat final. Les combine méthodes prennent combine_each chacune une fonction de combinaison qui spécifie comment combiner chaque paire d’éléments. Par conséquent, la combinable classe n’est pas limitée à 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 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 produit la sortie suivante.

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.

Pour plus d’informations sur la combinable classe, 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 , puis exécutez la commande suivante dans une fenêtre d’invite de commandes Visual Studio.

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

Voir aussi

Migration d’OpenMP au runtime d’accès concurrentiel
Conteneurs et objets parallèles