c++ - 声明减少向量,在 1 个线程上运行与没有 openmp 的结果不同
问题描述
即使我在 1 个线程上运行它,我的以下代码也会给出错误的答案。如果注释掉 for 循环之前的两个 pragma,则代码给出正确的结果。怎么会这样?我认为在 1 个线程上,使用 OpenMP 和不使用 OpenMP 没有区别,除了可能有一些小的开销。另外,我应该怎么做才能获得“正确的行为”?当我只有一个 for 循环时,我没有同样的问题,但是超过 1 个时,它不会像我想的那样工作。
#include<iostream>
#include<vector>
#include<algorithm>
#include<omp.h>
using namespace std;
#pragma omp declare reduction(vec_double_plus : std::vector<double> : \
std::transform(omp_out.begin(), omp_out.end(), omp_in.begin(), omp_out.begin(), std::plus<double>())) \
initializer(omp_priv = omp_orig)
int main() {
vector<int> v;
vector<double> w(2);
for (int i = 0; i < 1000; i++) {
if (i % 2 == 0) {
v.push_back(0);
}
else {
v.push_back(1);
}
}
#pragma omp parallel for reduction(vec_double_plus:w)
for (int i = 0; i < 500; i++) {
int r = v[i];
w[r] += i;
}
#pragma omp parallel for reduction(vec_double_plus:w)
for (int i = 500; i < 1000; i++) {
int r = v[i];
w[r] += i;
}
std::cout << w[0] << std::endl;
std::cout << w[1] << std::endl;
}
解决方案
问题是,代码假定来自外部范围的原始变量是用归约的中性元素初始化的——即w
全零。它将从此外部创建本地副本并将其再次添加到原始副本中。这甚至发生在单个线程上。
您可以更改代码以omp_priv
使用零进行初始化,如下所示:
initializer(omp_priv = decltype(omp_orig)(omp_orig.size()))
代码对我来说很熟悉,很抱歉造成混淆。我会修复原来的答案。
推荐阅读
- reactjs - 开玩笑 TypeError: x 不是函数
- spring-boot - 为什么@Cachable(...) 可以与@Bean return mock() 一起使用,但不能与@MockedBean 一起使用
- c# - 如何将可空字段值作为参数传递给不带可空参数的函数?
- android - 错误:[Dagger/MissingBinding] java.lang.Integer 不能在没有@Inject 构造函数或@Provides-annotated 方法的情况下提供
- vue.js - JSON 内容显示 Tiptap-Vuetify 的空白窗口?
- javascript - 我们如何通过存储在 JavaScript 中两个对象数组中的值来比较对象?
- rust - 如何拥有动态框
>? - python - 如何删除重复项?
- javascript - 兼容模式下正确使用JQuery
- sql - SQL - 聚合函数查询中 .* 和 * 之间的区别