【问题标题】:Auto-vectorization of scalar product in loop循环中标量积的自动矢量化
【发布时间】:2019-01-09 05:05:03
【问题描述】:

我正在尝试自动矢量化以下循环。下面我们用i-j-loop 在矩阵的下三角形上循环。不幸的是,矢量化报告无法矢量化(=转换为 AVX SIMD 指令)j 循环和 k 循环。但我认为这很简单,因为没有指针别名(#pragma ivdep 和编译器选项-D NOALIAS)并且数据(x:一维数组和 p:一维数组)对齐到 64 个字节。

if-statement 可能是一个问题,但即使使用if-free 解决方案(昂贵的移位操作和计算双精度符号),编译器也无法向量化此循环。

__assume_aligned(x, 64);
__assume_aligned(p, 64);
#pragma omp parallel for simd reduction(+:accum)
for ( int i = 1 ; i < N ; i++ ){ // loop over lower triangle (i,j), OpenMP SIMD LOOP WAS VECTORIZED
    for ( int j = 0 ; j < i ; j++ ){ // <-- remark #25460: No loop optimizations reported
        double __attribute__((aligned(64))) scalarp = 0.0;
        #pragma omp simd
        for ( int k=0 ; k < D ; k++ ){ // <-- remark #25460: No loop optimizations reported
            // scalar product of \sum_k x_{i,k} \cdot x_{j,k}
            scalarp += x[i*D + k] * x[j*D + k];
        }

        // Alternative to following if:
        // accum +=  - ( (long long) floor( - ( scalarp + p[i] + p[j] ) ) >> 63);
        #pragma ivdep
        if ( scalarp + p[i] + p[j] >= 0 ){ // check if condition is satisfied
            accum += 1;
        }
    }
}

它是否指的是每个 OpenMP 线程的 OpenMP 起点直到运行时才知道的问题?我认为这解决了simd 子句,英特尔的自动矢量化也意识到了这一点。

英特尔编译器:18.0.2 20180210

编辑:我已经查看了程序集,现在很明显代码已经被矢量化了,很抱歉让你们所有人接受。

【问题讨论】:

  • asm 是什么样的?外部循环的OpenMP SIMD LOOP WAS VECTORIZED 不是意味着使用 SIMD 对某些内容进行了矢量化吗?
  • vectorize 是什么意思?您希望编译器使用 SIMD 指令吗?如果是这种情况,那么我认为您当前的算法不可能,因为您正在以非顺序顺序访问您的数据。 (当您增加Ij 时,您会立即进入内存。)
  • 我认为在k 上对内循环进行矢量化对您的编译器来说应该没问题。你看过大会吗?
  • 当你在一个归约循环上抛出 omp simd 而不声明归约时,你是在自找麻烦;当然,问我们会发生什么毫无意义。也许循环已被丢弃为死代码。我们可能希望有一个选项可以在 opt-report 中指出死代码消除。
  • @tim18:死代码意味着,我不应该得到正确的结果,但我得到了正确的结果,所以循环不会被丢弃。

标签: c++ openmp intel auto-vectorization


【解决方案1】:

查看程序集确实很有帮助。代码已经矢量化。在这种特殊情况下,OpenMP SIMD LOOP WAS VECTORIZED 还负责处理内部循环。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-12
    • 2012-09-24
    • 2016-02-11
    • 1970-01-01
    • 1970-01-01
    • 2014-01-10
    相关资源
    最近更新 更多