2017-01-19 67 views
0

考虑一个简单的循环:gcc是否使用v *汇编指令提供更差/更慢的代码?

float f(float x[]) { 
    float p = 1.0; 
    for (int i = 0; i < 128; i++) 
    p += x[i]; 
    return p; 
} 

如果用-02 -march =的Haswell在GCC编译它,你得到:

f: 
      vmovss xmm0, DWORD PTR .LC0[rip] 
      lea  rax, [rdi+512] 
    .L2: 
      vaddss xmm0, xmm0, DWORD PTR [rdi] 
      add  rdi, 4 
      cmp  rdi, rax 
      jne  .L2 
      ret 
    .LC0: 
      .long 1065353216 

然而,英特尔C编译器提供了:

f: 
     xor  eax, eax          #3.3 
     pxor  xmm0, xmm0         #2.11 
     movaps xmm7, xmm0         #2.11 
     movaps xmm6, xmm0         #2.11 
     movaps xmm5, xmm0         #2.11 
     movaps xmm4, xmm0         #2.11 
     movaps xmm3, xmm0         #2.11 
     movaps xmm2, xmm0         #2.11 
     movaps xmm1, xmm0         #2.11 
..B1.2:       # Preds ..B1.2 ..B1.1 
     movups xmm8, XMMWORD PTR [rdi+rax*4]     #4.10 
     movups xmm9, XMMWORD PTR [16+rdi+rax*4]    #4.10 
     movups xmm10, XMMWORD PTR [32+rdi+rax*4]    #4.10 
     movups xmm11, XMMWORD PTR [48+rdi+rax*4]    #4.10 
     movups xmm12, XMMWORD PTR [64+rdi+rax*4]    #4.10 
     movups xmm13, XMMWORD PTR [80+rdi+rax*4]    #4.10 
     movups xmm14, XMMWORD PTR [96+rdi+rax*4]    #4.10 
     movups xmm15, XMMWORD PTR [112+rdi+rax*4]   #4.10 
     addps  xmm0, xmm8         #4.5 
     addps  xmm7, xmm9         #4.5 
     addps  xmm6, xmm10         #4.5 
     addps  xmm5, xmm11         #4.5 
     addps  xmm4, xmm12         #4.5 
     addps  xmm3, xmm13         #4.5 
     addps  xmm2, xmm14         #4.5 
     addps  xmm1, xmm15         #4.5 
     add  rax, 32          #3.3 
     cmp  rax, 128          #3.3 
     jb  ..B1.2  # Prob 99%      #3.3 
     addps  xmm0, xmm7         #2.11 
     addps  xmm6, xmm5         #2.11 
     addps  xmm4, xmm3         #2.11 
     addps  xmm2, xmm1         #2.11 
     addps  xmm0, xmm6         #2.11 
     addps  xmm4, xmm2         #2.11 
     addps  xmm0, xmm4         #2.11 
     movaps xmm1, xmm0         #2.11 
     movhlps xmm1, xmm0         #2.11 
     addps  xmm0, xmm1         #2.11 
     movaps xmm2, xmm0         #2.11 
     shufps xmm2, xmm0, 245        #2.11 
     addss  xmm0, xmm2         #2.11 
     addss  xmm0, DWORD PTR .L_2il0floatpacket.0[rip]  #2.11 
     ret              #5.10 
.L_2il0floatpacket.0: 
     .long 0x3f800000 

如果我们忽略循环展开,最明显的区别是使用vaddss和icc的gcc使用addss。

这两个装配件 之间存在性能差异,哪一个更好(忽略展开循环)?


在V前缀来自VEX coding scheme。看来你可以通过添加-xavx作为命令行标志的一部分来获得icc使用这些指令。然而,如果问题中两组程序之间存在任何性能差异,或者如果两者之间存在任何优势,问题仍然存在。

+0

为什么downvote? – eleanora

+0

也许是因为你好像根本没有做过任何研究。 – fuz

+0

@fuz我的研究是以可读格式获得程序集。我不知道如何确定哪个组件更好。 – eleanora

回答

5

以助记符v为前缀的指令是VEX编码指令。 VEX编码方案允许对每个SSE指令以及新的AVX指令和一些其他指令进行编码。有一个几乎1:传统指令和VEX之间1的对应编码具有下列不同操作的指令:

  • VEX编码SSE指令隐含零出对应于所使用的xmm寄存器操作数高的128位的ymm寄存器的指令。如果先前的指令在这些位中留下数据,则这避免了昂贵的部分寄存器更新。
  • VEX编码方案允许指令有一个额外的输出操作数,而不是覆盖其中一个输入操作数。这可以降低寄存器压力,并允许编译器生成更少的数据移动,从而稍微提高性能。
  • AVX指令只能使用VEX前缀进行编码,因为256位数据宽度无法通过任何其他方式传送。