如何:转换 OpenMP parallel for 循环以使用并发运行时
此示例演示了如何转换使用 OpenMP parallel 和 for 指令的基本循环来使用并发运行时 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 仅允许 parallel_for
构造中使用有符号整型索引类型,因此不能使用迭代器并行访问 C++ 标准库容器的元素。 并行模式库 (PPL) 提供 concurrency::parallel_for_each 算法,该算法在迭代容器(例如 C++ 标准库提供的容器)上并行执行任务。 它与 parallel_for
算法使用相同的分区逻辑。 parallel_for_each
算法类似于 C++ 标准库 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-count-primes.cpp
的文件中,再在 Visual Studio 命令提示符窗口中运行以下命令。
cl.exe /EHsc /openmp concrt-omp-count-primes.cpp
另请参阅
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈