Share via


Comment : écrire une boucle parallel_for_each

Cet exemple montre comment utiliser la concurrency::parallel_for_each algorithme pour calculer le nombre de nombres premiers dans une std::array objet 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.

serial version:
found 17984 prime numbers
took 6115 ms

parallel version:
found 17984 prime numbers
took 1653 ms

Compilation du code

Pour compiler le code, copiez-le et collez-le dans un projet Visual Studio ou le coller dans un fichier nommé parallèle-count-primes.cpp , puis exécutez la commande suivante dans une fenêtre d'invite de commande 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 verrouillage, par exemple, la concurrency::combinable (classe), afin d'éliminer un 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