在向量上声明缩减,在 1 个线程上运行给出的结果与没有 openmp 的结果不同

Declare Reduction over Vector, Running on 1 thread gives different result than without openmp

本文关键字:结果 openmp 运行 声明 向量 线程      更新时间:2023-10-16

我有以下一段代码,即使我在 1 个线程上运行它,它也给出了错误的答案。如果注释掉 for 循环之前的两个杂注,则代码将给出正确的结果。这怎么可能?我认为在 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()))

代码对我来说看起来很熟悉,很抱歉造成混乱。我会修复原始答案。