Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
In questo esempio viene illustrato come convertire un ciclo di base che usa il parallelismo OpenMP e per le direttive per usare l'algoritmo Concurrency Runtime concurrency::p arallel_for.
Esempio : conteggio dei numeri primi
Questo esempio usa 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 il seguente output:
Using OpenMP...
found 107254 prime numbers.
Using the Concurrency Runtime...
found 107254 prime numbers.
L'algoritmo parallel_for e OpenMP 3.0 consentono al tipo di indice di essere un tipo integrale con segno o un tipo integrale senza segno. L'algoritmo parallel_for assicura inoltre che l'intervallo specificato non sovraflow un tipo con segno. Le versioni OpenMP 2.0 e 2.5 consentono solo tipi di indice integrale con segno. OpenMP non convalida anche l'intervallo di indici.
La versione di questo esempio che usa il runtime di concorrenza usa anche un oggetto concurrency::combinable al posto della direttiva atomica per incrementare il valore del contatore senza richiedere la sincronizzazione.
Per altre informazioni su parallel_for e altri algoritmi paralleli, vedere Algoritmi paralleli. Per altre informazioni sulla combinable classe , vedere Contenitori e oggetti paralleli.
Esempio: usare std::array
In questo esempio viene modificato quello precedente per agire su un oggetto std::array anziché su una matrice nativa. Poiché le versioni OpenMP 2.0 e 2.5 consentono i tipi di indice integrale con segno solo in un parallel_for costrutto, non è possibile usare iteratori per accedere agli elementi di un contenitore della libreria standard C++ in parallelo. La libreria PPL (Parallel Patterns Library) fornisce l'algoritmo concurrency::p arallel_for_each , che esegue attività in parallelo su un contenitore iterativo, ad esempio quelli forniti dalla libreria standard C++. Usa la stessa logica di partizionamento usata dall'algoritmo parallel_for . L'algoritmo parallel_for_each è simile all'algoritmo std::for_each della libreria standard C++, ad eccezione del fatto che l'algoritmo parallel_for_each esegue le attività contemporaneamente.
// 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 oppure incollarlo in un file denominato concrt-omp-count-primes.cpp e quindi eseguire il comando seguente in una finestra del prompt dei comandi di Visual Studio.
cl.exe /EHsc /openmp concrt-omp-count-primes.cpp
Vedi anche
Migrazione da OpenMP al runtime di concorrenza
Algoritmi paralleli
Contenitori e oggetti paralleli