Comment : convertir une boucle OpenMP parallèle pour utiliser le runtime d'accès concurrentiel
Cet exemple montre comment convertir une boucle de base qui utilise l'OpenMP parallèles et pour directives pour utiliser la simultanéité d'exécution concurrency::parallel_for algorithme.
Exemple
Cet exemple utilise OpenMP et le runtime d'accès concurrentiel pour calculer le nombre de nombres premiers dans un tableau de valeurs aléatoires.
// concrt-omp-count-primes.cpp
// compile with: /EHsc /openmp
#include <ppl.h>
#include <random>
#include <array>
#include <iostream>
using namespace concurrency;
using namespace std;
// 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;
}
// Uses OpenMP to compute the count of prime numbers in an array.
void omp_count_primes(int* a, size_t size)
{
if (size == 0)
return;
size_t count = 0;
#pragma omp parallel for
for (int i = 0; i < static_cast<int>(size); ++i)
{
if (is_prime(a[i])) {
#pragma omp atomic
++count;
}
}
wcout << L"found " << count
<< L" prime numbers." << endl;
}
// Uses the Concurrency Runtime to compute the count of prime numbers in an array.
void concrt_count_primes(int* a, size_t size)
{
if (size == 0)
return;
combinable<size_t> counts;
parallel_for<size_t>(0, size, [&](size_t i)
{
if (is_prime(a[i])) {
counts.local()++;
}
});
wcout << L"found " << counts.combine(plus<size_t>())
<< L" prime numbers." << endl;
}
int wmain()
{
// The length of the array.
const size_t size = 1000000;
// Create an array and initialize it with random values.
int* a = new int[size];
mt19937 gen(42);
for (size_t i = 0; i < size; ++i) {
a[i] = gen();
}
// Count prime numbers by using OpenMP and the Concurrency Runtime.
wcout << L"Using OpenMP..." << endl;
omp_count_primes(a, size);
wcout << L"Using the Concurrency Runtime..." << endl;
concrt_count_primes(a, size);
delete[] a;
}
Cet exemple génère la sortie suivante.
Using OpenMP...
found 107254 prime numbers.
Using the Concurrency Runtime...
found 107254 prime numbers.
L'algorithme parallel_for et OpenMP 3.0 permettent au type d'index d'être de type intégral signé ou de type intégral non signé.L'algorithme parallel_for vérifie également que la plage spécifiée ne dépasse pas un type signé.Les versions OpenMP 2.0 et 2.5 n'autorisent que les types d'index intégraux signés.OpenMP ne valide pas la plage d'index.
La version de cet exemple utilise la simultanéité d'exécution utilise également un concurrency::combinable d'objet à la place de la atomique directive pour incrémenter la valeur du compteur sans nécessiter de synchronisation.
Pour plus d'informations sur parallel_for et d'autres algorithmes parallèles, consultez Algorithmes parallèles.Pour plus d'informations sur la classe combinable, consultez Conteneurs et objets parallèles.
Cet exemple modifie l'exemple précédent pour agir sur un objet std::array plutôt que sur un tableau natif.Étant donné que les versions OpenMP 2.0 et 2.5 n'autorisent que les types d'index intégraux signés dans un élément parallelfor, vous ne pouvez pas utiliser d'itérateurs pour accéder aux éléments d'un conteneur de la bibliothèque de modèles Standard (STL) en parallèle.La bibliothèque de motifs parallèle (PPL) fournit la concurrency::parallel_for_each algorithme, qui effectue des tâches, en parallèle sur un conteneur itératif tels que ceux fournis par la STL.Il utilise la même logique de partitionnement que l'algorithme parallel_for.L'algorithme parallel_for_each ressemble à l'algorithme std::for_each STL, à l'exception près que l'algorithme parallel_for_each exécute les tâches simultanément.
// Uses OpenMP to compute the count of prime numbers in an
// array object.
template<size_t Size>
void omp_count_primes(const array<int, Size>& a)
{
if (a.size() == 0)
return;
size_t count = 0;
int size = static_cast<int>(a.size());
#pragma omp parallel for
for (int i = 0; i < size; ++i)
{
if (is_prime(a[i])) {
#pragma omp atomic
++count;
}
}
wcout << L"found " << count
<< L" prime numbers." << endl;
}
// Uses the Concurrency Runtime to compute the count of prime numbers in an
// array object.
template<size_t Size>
void concrt_count_primes(const array<int, Size>& a)
{
if (a.size() == 0)
return;
combinable<size_t> counts;
parallel_for_each(begin(a), end(a), [&counts](int n)
{
if (is_prime(n)) {
counts.local()++;
}
});
wcout << L"found " << counts.combine(plus<size_t>())
<< L" prime numbers." << endl;
}
Compilation du code
Copiez l'exemple de code, collez-le dans un projet Visual Studio et collez-le dans un fichier nommé concrt-omp-count-primes.cpp , puis exécutez la commande suivante dans une fenêtre d'invite de commande Visual Studio.
cl.exe /EHsc /openmp concrt-omp-count-primes.cpp