HOW TO:轉換 OpenMP parallel for 迴圈來使用並行執行階段
本範例將示範如何轉換基本迴圈使用 OpenMP 平行 和 的 指示詞,可使用並行執行階段 concurrency::parallel_for 演算法。
範例
這個範例使用 OpenMP 和並行執行階段,計算隨機值陣列中質數的計數。
// 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;
}
這個範例產生下列輸出。
Using OpenMP...
found 107254 prime numbers.
Using the Concurrency Runtime...
found 107254 prime numbers.
parallel_for 演算法和 OpenMP 3.0 允許索引類型為帶正負號的整數類資料型別或不帶正負號的整數類資料型別。parallel_for 演算法也會確定指定的範圍不溢出帶正負號型別。OpenMP 2.0 和 2.5 版只允許帶正負號的整數索引類型。OpenMP 也不會驗證索引範圍。
這個範例中使用並行存取執行階段版本也會使用 concurrency::combinable 物件的位置不可部分完成指示詞,以遞增的計數器值,而不需要同步處理。
如需 parallel_for 和其他平行演算法的詳細資訊,請參閱平行演算法。如需 combinable 類別的詳細資訊,請參閱平行容器和物件。
這個範例將前述範例修改為作用於 std::array 物件,而不是原生陣列物。因為 OpenMP 2.0 和 2.5 版在 parallelfor 建構中只允許帶正負號的整數索引類型,所以您不可使用 Iterator 平行存取標準樣板程式庫 (STL) 容器中的項目。平行模式文件庫 (PPL) 提供 concurrency::parallel_for_each 會執行工作,以平行方式,在一個反覆的容器,例如 STL 所提供的演算法。它會使用 parallel_for 演算法所使用的相同分割邏輯。parallel_for_each 演算法與 STL std::for_each 演算法很相似,不過 parallel_for_each 演算法會執行並行工作。
// 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;
}
編譯程式碼
將範例程式碼複製並貼上它在 Visual Studio 專案中,或將它貼在檔名為 concrt omp 計數-primes.cpp ,然後執行下列命令,Visual Studio 的命令提示字元] 視窗中。
cl.exe /EHsc /openmp concrt-omp-count-primes.cpp