gpt4 book ai didi

c++ - Intel 编译器 (C++) 问题与 std::vector 上的 OpenMP 缩减

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:32:49 28 4
gpt4 key购买 nike

从 OpenMP 4.0 开始,支持用户定义的缩减。所以我在 C++ 中完全从 here 定义了对 std::vector 的归约。 .它适用于 GNU/5.4.0 和 GNU/6.4.0,但它返回随机值以减少 intel/2018.1.163。

这是例子:

#include <iostream>
#include <vector>
#include <algorithm>
#include "omp.h"

#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() {

omp_set_num_threads(4);
int size = 100;
std::vector<double> w(size,0);

#pragma omp parallel for reduction(vec_double_plus:w)
for (int i = 0; i < 4; ++i)
for (int j = 0; j < w.size(); ++j)
w[j] += 1;

for(auto i:w)
if(i != 4)
std::cout << i << std::endl;

return 0;
}

每个线程将所有 w 个条目(其本地 w)加 1,最后将所有条目加在一起(归约)。对于 GNU,所有 w 条目的结果都是 4,但对于 intel 编译器是随机的。有谁知道这里发生了什么?

最佳答案

这似乎是英特尔编译器中的错误,我可以使用不涉及 vector 的 C 示例可靠地重现它:

#include <stdio.h>

void my_sum_fun(int* outp, int* inp) {
printf("%d @ %p += %d @ %p\n", *outp, outp, *inp, inp);
*outp = *outp + *inp;
}

int my_init(int* orig) {
printf("orig: %d @ %p\n", *orig, orig);
return *orig;
}

#pragma omp declare reduction(my_sum : int : my_sum_fun(&omp_out, &omp_in) initializer(omp_priv = my_init(&omp_orig))

int main()
{
int s = 0;
#pragma omp parallel for reduction(my_sum : s)
for (int i = 0; i < 2; i++)
s+= 1;

printf("sum: %d\n", s);
}

输出:

orig: 0 @ 0x7ffee43ccc80
0 @ 0x7ffee43ccc80 += 1 @ 0x7ffee43cc780
orig: 1 @ 0x7ffee43ccc80
1 @ 0x7ffee43ccc80 += 2 @ 0x2b56d095ca80
sum: 3

它将归约操作应用到原始变量之前从原始值初始化私有(private)拷贝。这会导致错误的结果。

作为解决方法,您可以手动添加障碍:

#pragma omp parallel reduction(vec_double_plus : w)
{
#pragma omp for
for (int i = 0; i < 4; ++i)
for (int j = 0; j < w.size(); ++j)
w[j] += 1;
#pragma omp barrier
}

关于c++ - Intel 编译器 (C++) 问题与 std::vector 上的 OpenMP 缩减,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50222760/

28 4 0
文章推荐: c++ - 将 unique_ptr 作为 unique_ptr 返回