Procedura: convertire un ciclo OpenMP parallel for per l'utilizzo del runtime di concorrenza
In questo esempio viene illustrato come convertire un ciclo di base che utilizza il OpenMP parallelo e per le direttive per l'utilizzo di Common Language Runtime concorrenza concurrency::parallel_for algoritmo.
Esempio
In questo esempio vengono utilizzati sia OpenMP che il runtime di concorrenza per calcolare il conteggio dei numeri primi in una matrice di valori casuali.
// 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;
}
Questo esempio produce l'output che segue.
Using OpenMP...
found 107254 prime numbers.
Using the Concurrency Runtime...
found 107254 prime numbers.
L'algoritmo parallel_for e OpenMP 3.0 consentono che il tipo di indice sia un tipo integrale con segno oppure un tipo integrale senza segno.L'algoritmo parallel_for assicura inoltre che l'intervallo specificato non superi un tipo con segno.Nelle versioni 2.0 e 2.5 di OpenMP sono consentiti solo tipi di indice integrali con segno.OpenMP inoltre non convalida l'intervallo dell'indice.
Utilizza inoltre la versione di questo esempio utilizza il Runtime della concorrenza un concurrency::combinable oggetto anziché il atomico direttiva per incrementare il valore del contatore senza la necessità di sincronizzazione.
Per ulteriori informazioni su parallel_for e altri algoritmi paralleli, vedere Algoritmi paralleli.Per ulteriori informazioni sulla classe combinable, vedere Contenitori e oggetti paralleli.
In questo esempio viene modificato l'esempio precedente in modo che si possa agire su un oggetto std::array anziché su una matrice nativa.Poiché nelle versioni 2.0 e 2.5 di OpenMP sono consentiti solo tipi di indice integrali con segno in un costrutto parallelfor, non è possibile utilizzare gli iteratori per accedere agli elementi di un contenitore STL (Standard Template Library) in parallelo.La libreria di modelli parallela (PPL) fornisce la concurrency::parallel_for_each algoritmo, che svolge i compiti, in parallelo su un contenitore iterativo, ad esempio quelli forniti da STL.Utilizza la stessa logica di partizionamento utilizzata dall'algoritmo parallel_for.L'algoritmo parallel_for_each è simile all'algoritmo std::for_each STL, con l'unica differenza che l'algoritmo parallel_for_each esegue le attività simultaneamente.
// 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;
}
Compilazione del codice
Copiare il codice di esempio e incollarlo in un progetto di Visual Studio o incollarlo in un file denominato concrt-omp-conteggio-primes.cpp e quindi eseguire il comando riportato di seguito in una finestra del prompt dei comandi di Visual Studio.
cl.exe /EHsc /openmp concrt-omp-count-primes.cpp