Partage via


Guide pratique pour écrire une parallel_for_each boucle

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

Exemple

L’exemple suivant calcule le nombre de nombres premiers dans un tableau deux fois. L’exemple utilise d’abord l’algorithme std::for_each pour calculer le nombre en série. L’exemple utilise ensuite l’algorithme parallel_for_each pour effectuer la même tâche en parallèle. L'exemple affiche également sur 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;

// Returns the number of milliseconds that it takes to call the passed in function.
template <class Function>
__int64 time_call(Function&& f)
{
    __int64 begin = GetTickCount();
    f();
    return GetTickCount() - begin;
}

// Determines whether the input is a prime.
bool is_prime(int n)
{
    if (n < 2)
    {
        return false;
    }

    for (int i = 2; i < int(std::sqrt(n)) + 1; ++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++;
        });

    // Use the for_each algorithm to count, serially, the number
    // of prime numbers in the array.
    LONG prime_count = 0L;
    __int64 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, in parallel, the number
    // of prime numbers in the array.
    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 qui a quatre cœurs.

serial version:
found 17984 prime numbers
took 125 ms

parallel version:
found 17984 prime numbers
took 63 ms

Compilation du code

Pour compiler le code, copiez-le, 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 transmet à l’algorithme parallel_for_each utilise la InterlockedIncrement fonction pour activer les itérations parallèles de la boucle pour incrémenter le compteur simultanément. Si vous utilisez des fonctions telles que InterlockedIncrement pour synchroniser l’accès aux ressources partagées, vous pouvez présenter des goulots d’étranglement des performances dans votre code. Vous pouvez utiliser un mécanisme de synchronisation sans verrou, par exemple, la concurrency::combinable classe, pour éliminer l’accès simultané aux ressources partagées. Pour obtenir un exemple qui utilise la combinable classe de cette façon, consultez Guide pratique pour améliorer les performances.

Voir aussi

Algorithmes parallèles
parallel_for_each Fonction