英特尔编译器(C ++)在std :: vector上具有OpenMP减少问题

阿巴里斯

从OpenMP 4.0开始,支持用户定义的还原。所以我正是从这里定义了C ++中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,最后将它们全部加在一起(归约)。对于所有w条目,GNU的结果是4,而intel编译器的结果是随机的。有人知道这里发生了什么吗?

Zulan

这似乎是英特尔编译器中的错误,我可以使用不涉及向量的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

从原始值初始化私有副本之前,它将归约操作应用于原始变量这会导致错误的结果。

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

#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
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

使用openmp时,英特尔C编译器给出错误的输出

在 Windows 上使用英特尔 C++ 编译器无法执行程序

英特尔C ++编译器:如何在宏定义/定义中编译和链接openmp编译指示?

这里有人对基准英特尔C ++编译器和GCC进行过测试吗?

无法在 Windows 上使用英特尔编译器编译示例 boost::multiprecision

带有 gcc 7.1/8.1 的英特尔编译器 17.0

如何使用英特尔Windows编译器在命令行上禁用C ++ 0x和/或C ++ 11?

有效使用英特尔编译器SVML`__m128 _mm_sincos_ps()`

英特尔编译器:将fortran编译库链接到C的主程序

英特尔编译器内联大小

英特尔WebRTC 2.1.1服务器连接问题

英特尔945板上的SATA驱动器

英特尔处理器上的浮点组件

在哪里可以下载英特尔C ++编译器?

英特尔C ++编译器-常量字符串可修改

英特尔C ++编译器给出“此平台不支持卸载结构”错误

英特尔迅驰双核处理器和英特尔迅驰2之间有区别吗?

带有C ++ 14的英特尔针

存储转发地址与数据:英特尔优化指南中STD和STA有什么区别?

为什么英特尔编译器会忽略英特尔MIC的非临时预取编译指示?

C ++编译器:“类std :: vector <std :: vector <char>>”没有名为“ emplace_back”的成员

英特尔icpc和C ++ 14:如何constexpr std :: complex?

具有未定义行为的C ++代码,编译器生成std :: exception

英特尔加载固有问题

英特尔Q8200是否具有缓存预取器?

使用英特尔 Fortran 编译器编译独立的 DLL 文件

编译器如何区分std :: vector的构造函数?

英特尔软件安装中的问题

英特尔OpenCL Beignet问题