2016-07-28 105 views
3

我想通过使用AVX intrinsics来优化一些代码。一个非常简单的测试用例编译,但告诉我,我的循环没有矢量化的原因有很多,我不明白。这个C矢量为什么不循环自动矢量化?

这是完整的程序,simple.c

#include <math.h> 
#include <stdlib.h> 
#include <assert.h> 
#include <immintrin.h> 

int main(void) 
{ 

    __m256 * x = (__m256 *) calloc(1024,sizeof(__m256));  

    for (int j=0;j<32;j++) 
    x[j] = _mm256_set1_ps(1.); 

    return(0); 
} 

这是命令行: GCC simple.c -O1 -fopenmp -ffast-数学-lm -mavx2 -ftree-矢量化-fopt-信息-VEC错过

这是输出:

  • simple.c:11:3:注意:不是矢量:不支持的数据类型
  • simple.c: 11:3:注意:无法确定矢量化因子。
  • simple.c:6:5:note:not vectorized:没有足够的data-refs在基本块中。
  • simple.c:11:3:note:not vectorized:没有足够的data-refs在基本块中。
  • simple.c:6:5:note:not vectorized:没有足够的data-refs在基本块中。
  • simple.c:6:5:note:not vectorized:没有足够的data-refs在基本块中。

我有gcc版本5.4。

任何人都可以帮助我解释这些消息,并了解发生了什么?

回答

3

您已经手动使用intrinsics进行矢量化,所以gcc没有什么可以自动向量化。这导致无趣的警告,我试图自动向量化内部或循环计数器增量。

我从gcc 5.3(on the Godbolt compiler explorer)中获得了很好的asm,如果我没有做一些愚蠢的事情,比如编写一个可以优化的函数,或者尝试编译它只有-O1

#include <immintrin.h> 

void set_to_1(__m256 * x) { 
    for (int j=0;j<32;j++) 
    x[j] = _mm256_set1_ps(1.); 
} 

    push rbp 
    lea  rax, [rdi+1024] 
    vmovaps ymm0, YMMWORD PTR .LC0[rip] 
    mov  rbp, rsp 
    push r10      # gcc is weird with r10 in functions with ymm vectors 
.L2:         # this is the vector loop 
    vmovaps YMMWORD PTR [rdi], ymm0 
    add  rdi, 32 
    cmp  rdi, rax 
    jne  .L2 
    vzeroupper 
    pop  r10 
    pop  rbp 
    ret 

.LC0: 
    .long 1065353216 
    ... repeated several times because gcc failed to use a vbroadcastss load or generate the constant on the fly 

我的确从-O1得到几乎相同的ASM,但使用-O1不优化东西拿走不看什么GCC将真正做一个好办法。

+0

是否有一个有用的详细文档解释GCC有关自动矢量化的信息和警告?我发现输出有时会令人困惑。 – Jens

+0

@Jens:不知道;我总是只看asm输出来看看编译器做了什么。在复杂函数中,调试器中的单步可以帮助找到主循环(在去皮序言/结语未对齐迭代的噪声中)。 –

+0

谢谢彼得。我认为这些消息意味着某些东西是错误的。到目前为止,您的回答和我的经验表明,真正无法替代对asm的一些熟悉。最好早点知道这一点,而不是晚点。 – ghostofsandy