Partager via


Comment : écrire une boucle parallel_for_each

Cet exemple montre comment utiliser l'algorithme concurrency::parallel_for_each pour calculer la quantité de nombres premiers dans un objet std::array en parallèle.

Exemple

L'exemple suivant calcule la quantité de nombres premiers dans un tableau à deux reprises. L'exemple utilise d'abord l'algorithme std::for_each pour calculer le numéro séquentiel. L'exemple utilise ensuite l'algorithme parallel_for_each pour effectuer la même tâche en parallèle. L'exemple imprime également dans la console le temps requis pour effectuer les deux calculs.

// parallel-count-primes.cpp 
// compile with: /EHsc
#include <windows.h>
#include <ppl.h>
#include <iostream>
#include <algorithm>
#include <array>

using namespace concurrency;
using namespace std;

// Calls the provided work function and returns the number of milliseconds  
// that it takes to call that function. 
template <class Function>
__int64 time_call(Function&& f)
{
   __int64 begin = GetTickCount();
   f();
   return GetTickCount() - begin;
}

// Determines whether the input value is prime. 
bool is_prime(int n)
{
   if (n < 2)
      return false;
   for (int i = 2; i < n; ++i)
   {
      if ((n % i) == 0)
         return false;
   }
   return true;
}

int wmain()
{
   // Create an array object that contains 200000 integers. 
   array<int, 200000> a;

   // Initialize the array such that a[i] == i. 
   int n = 0;
   generate(begin(a), end(a), [&] {
      return n++;
   });

   LONG prime_count;
   __int64 elapsed;

   // Use the for_each algorithm to count the number of prime numbers 
   // in the array serially.
   prime_count = 0L;
   elapsed = time_call([&] {
      for_each (begin(a), end(a), [&](int n ) { 
         if (is_prime(n))
            ++prime_count;
      });
   });
   wcout << L"serial version: " << endl
         << L"found " << prime_count << L" prime numbers" << endl
         << L"took " << elapsed << L" ms" << endl << endl;

   // Use the parallel_for_each algorithm to count the number of prime numbers 
   // in the array in parallel.
   prime_count = 0L;
   elapsed = time_call([&] {
      parallel_for_each (begin(a), end(a), [&](int n ) { 
         if (is_prime(n))
            InterlockedIncrement(&prime_count);
      });
   });
   wcout << L"parallel version: " << endl
         << L"found " << prime_count << L" prime numbers" << endl
         << L"took " << elapsed << L" ms" << endl << endl;
}

L'exemple de sortie suivant concerne un ordinateur avec quatre processeurs.

  

Compilation du code

Pour compiler le code, copiez-le puis collez-le dans un projet Visual Studio , ou collez-le dans un fichier nommé parallel-count-primes.cpp puis exécutez la commande suivante dans une fenêtre d'invite de commandes Visual Studio.

cl.exe /EHsc parallel-count-primes.cpp

Programmation fiable

L'expression lambda que l'exemple passe à l'algorithme parallel_for_each utilise la fonction InterlockedIncrement pour permettre aux itérations parallèles de la boucle d'incrémenter le compteur simultanément. Si vous utilisez des fonctions telles qu'InterlockedIncrement pour synchroniser l'accès aux ressources partagées, vous pouvez introduire des goulots d'étranglement au niveau des performances dans votre code. Vous pouvez utiliser un mécanisme de synchronisation sans verrou, par exemple la classe concurrency::combinable, pour éliminer l'accès simultané aux ressources partagées. Pour obtenir un exemple qui utilise la classe combinable de cette manière, consultez Comment : utiliser la classe combinable pour améliorer les performances.

Voir aussi

Référence

parallel_for_each, fonction

Concepts

Algorithmes parallèles