2016-07-28 107 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