【问题标题】:Is OpenMP vectorization guaranteed?是否保证 OpenMP 矢量化?
【发布时间】:2018-06-21 04:02:27
【问题描述】:

OpenMP 标准是否保证 #pragma omp simd 工作,即如果编译器无法对代码进行矢量化,编译是否会失败?

#include <cstdint>
void foo(uint32_t r[8], uint16_t* ptr)
{
    const uint32_t C = 1000;
    #pragma omp simd
    for (int j = 0; j < 8; ++j)
        if (r[j] < C)
            r[j] = *(ptr++);
}

gcc 和 clang 无法对此进行矢量化,但根本不会抱怨(除非您使用 -fopt-info-vec-optimized-missed 等)。

【问题讨论】:

标签: c++ openmp vectorization simd


【解决方案1】:

不,不能保证。我能找到的OpenMP 4.5 standard 的相关部分(强调我的):

(1.3) 当任何线程遇到 simd 构造时,与构造关联的循环的迭代可能使用线程可用的 SIMD 通道并发执行。

(2.8.1) 可以将 simd 构造应用于循环以指示循环可以转换为 SIMD 循环(即循环的多次迭代可以同时执行使用SIMD 指令)。

(附录 C)在任何给定时间并发执行的迭代次数由实现定义。

(1.2.7) 定义的实现:必须由实现记录的行为,并且允许在不同的兼容实现之间变化。允许实现将此行为定义为未指定。

【讨论】:

  • 它可能会为编译器提供一些关于可能的转换的信息,由于语言问题(例如别名),它无法自动推断出这些信息。 TBH,就个人而言,我不太喜欢这种暗示。
  • 但是,如果您在编译失败时甚至没有收到编译器警告(尤其是后来由于代码或编译器版本的更改而导致的回归),那么它就没有用了。而且它可能会很容易地导致错误的代码,因为你基本上会强制编译器忽略它自己的分析:godbolt.org/g/dp5JVR(它放弃了 ptr++ 操作!)
  • @Trass3r:你确定这对#pragma openmp simd 是合法的,而不是编译器错误吗? OTOH,我看到 ICC17 也这样做(但它不理解 -march=haswell,仅理解 -march=native-xHOST,因此它使用 AVX512。)GCC 根本不使用 -fopenmp 对其进行矢量化。 godbolt.org/g/H7u3Cw。但是即使我们删除了++,它也不会向量化,因此即使没有#pragmagodbolt.org/g/rV2i5m,ICC 的输出也是有效的。请注意,您通常不需要simdlengcc -march=bdver2 或其他东西(设置 -mprefer-avx128`)可能很重要
  • 英特尔编译器默认在启用 omp simd 但不会导致矢量化时抛出诊断。 gnu 和 clang 编译器有更多忽略 omp simd 的情况,因此此类诊断可能很烦人。提出的案例看起来不像您想要尝试矢量化的案例,即使可能会考虑一种方法来处理循环携带的依赖关系。
  • @tim18:理论上,自动矢量化可以使用相同的技术that's possible for manual vectorization,特别是对于 AVX512 有这样的指令:vpexpandd ymm1{k1}, ymm2 。在实践中,自动矢量化目前无法处理它(例如,没有编译指示,只是普通的旧 autovec,甚至没有针对 AVX512 的 ICC18)。
猜你喜欢
  • 1970-01-01
  • 2016-03-20
  • 2021-12-15
  • 2013-01-29
  • 2016-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-11
相关资源
最近更新 更多