简单循环:用gcc进行矢量化

时间:2016-03-08 14:20:10

标签: gcc vectorization

在我的笔记本电脑上(ubuntu.14 + gcc-5.x),我有AVX:

~> tail /proc/cpuinfo 
   model name   : Intel(R) Core(TM) i7-3687U CPU @ 2.10GHz
   flags        : ... sse sse2 ... avx

我编译这个非常简单的代码:

~> more test.c 
  #include <stdio.h>
  void main() {
    int i=0; double a=1.;
    for(i=0;i<1000000;i++) a+=i;
    printf("%f\n", a); // printf: avoid compiler optim (dummy var suppression)
  }
~> make
   gcc -O2 -march=native -mavx -ftree-vectorize -funroll-loops -fopt-info-vec -fopt-info-loop -o test.exe test.c
   test.c:4:3: note: loop unrolled 7 times

我不明白循环是否真的&#34;真的&#34;消息说,矢量化! Objdump告诉:

~> objdump -S test.exe | grep add
   40041d:  48 83 c4 08             add    $0x8,%rsp
   4004a9:  c5 fb 58 c2             vaddsd %xmm2,%xmm0,%xmm0
   4004b8:  c5 fb 58 ec             vaddsd %xmm4,%xmm0,%xmm5
   4004cb:  c5 53 58 c7             vaddsd %xmm7,%xmm5,%xmm8
   4004e1:  c4 41 3b 58 da          vaddsd %xmm10,%xmm8,%xmm11
   4004ea:  83 c0 08                add    $0x8,%eax
   4004f2:  c4 41 23 58 f5          vaddsd %xmm13,%xmm11,%xmm14
   4004f7:  c5 8b 58 d1             vaddsd %xmm1,%xmm14,%xmm2
   4004fb:  c5 eb 58 e3             vaddsd %xmm3,%xmm2,%xmm4
   4004ff:  c5 db 58 c6             vaddsd %xmm6,%xmm4,%xmm0
   4005bb:  48 01 c6                add    %rax,%rsi
   40067d:  48 83 c3 01             add    $0x1,%rbx
   400686:  48 83 c4 08             add    $0x8,%rsp
   4006a8:  48 83 c4 08             add    $0x8,%rsp

最后,我得到了&#34; vadd s d&#34; (whit a&#34; v&#34;这似乎代表&#34;矢量化&#34;)但我没有&#34;添加 p d&#34;我原以为是?...

我的理解是&#34;添加 s d&#34;是标量加法(= 1个常规加法),并且&#34;添加 p d&#34;包装添加(=在1个循环中矢量化的几个添加物)。此外,我不明白&#34; v 添加 s d&#34;与&#34;添加 p d&#34; :这些应该是一样的吗? (谷歌这没有给出相关答案)

为什么我没有得到&#34; addpd&#34; ?缺少编译选项?代码中缺少提示/编译指示?或者是合乎逻辑的,如果是的话为什么?

FH

更新

消息说它已被矢量化,但事实并非如此,我没有加速:

~> more test.c 
   #include <stdio.h>
   void main() {
     unsigned int i=0; double a=1.;
     for(i=0;i<3000000000;i++) a+=i;
     printf("%f\n", a); // printf : avoid compiler optimisation what suppress a as it's a dummy variable !
   }
~> make
   gcc -O2 -march=native -o test.novec.exe test.c
   gcc -O2 -march=native -mavx -ftree-vectorize -funroll-loops -fopt-info-vec -fopt-info-loop -o test.vec.exe test.c
   test.c:4:3: note: loop unrolled 7 times
~> time ./test.novec.exe 
   4499999997067113984.000000
   real 0m2.927s
   user 0m2.928s
   sys  0m0.000s
~> time ./test.vec.exe
   4499999997067113984.000000
   real 0m2.926s
   user 0m2.924s
   sys  0m0.000s

...除非我添加-ffast-math(或包含-ffast-math的-Ofast):

~> make
   gcc -O2 -march=native -mavx -ftree-vectorize -funroll-loops -fopt-info-vec -fopt-info-loop -ffast-math -o test.vec.fm.exe test.c
   test.c:4:3: note: loop vectorized
   test.c:4:30: note: loop unrolled 3 times
~> time ./test.vec.fm.exe 
   4499999999597346816.000000
   real 0m1.980s
   user 0m1.980s
   sys  0m0.000s

1 个答案:

答案 0 :(得分:0)

addsdaddpd是传统的SSE2 SIMD insn。 vaddsdvaddpd是较新的AVX SIMD insn。 this page似乎提供了两者之间的良好比较:它是一种更灵活的编码,具有更高的精度。