微融合和寻址模式

时间:2014-09-25 19:33:21

标签: assembly x86 cpu intel iaca

我使用Intel® Architecture Code Analyzer(IACA)找到了意想不到的东西(对我而言)。

使用[base+index]寻址

的以下说明
addps xmm1, xmmword ptr [rsi+rax*1]
根据IACA,

没有微熔丝。但是,如果我像这样使用[base+offset]

addps xmm1, xmmword ptr [rsi]

IACA报告它确实融合了。

Intel optimization reference manual的第2-11节给出了以下作为“可以由所有解码器处理的微融合微操作”的示例“

FADD DOUBLE PTR [RDI + RSI*8]

Agner Fog's optimization assembly manual还提供了使用[base+index]寻址的微操作融合的示例。例如,请参见第12.2节“Core2上的相同示例”。那么正确的答案是什么?

3 个答案:

答案 0 :(得分:9)

注意:自从我写下这个答案以来,Peter也对Haswell和Skylake进行了测试,并将结果整合到上面接受的答案中(特别是,我归于Skylake的大部分改进似乎实际上都出现在Haswell )。您应该看到that answer了解CPU的行为纲要,这个答案(尽管没有错)主要是历史感兴趣。

我的测试表明,在 Skylake 至少 1 上,处理器完全融合了复杂的寻址模式,与Sandybridge不同。

也就是说,Peter上面发布的代码的 1-arg 2-arg 版本以相同的周期数运行,具有相同的uop数派遣和退休。

我的结果:

./uop-test的效果统计信息:

     23.718772      task-clock (msec)         #    0.973 CPUs utilized          
    20,642,233      cycles                    #    0.870 GHz                    
    80,111,957      instructions              #    3.88  insns per cycle        
    60,253,831      uops_executed_thread      # 2540.344 M/sec                  
    80,295,685      uops_issued_any           # 3385.322 M/sec                  
    80,176,940      uops_retired_retire_slots # 3380.316 M/sec                  

   0.024376698 seconds time elapsed

./uop-test x的效果统计信息:

     13.532440      task-clock (msec)         #    0.967 CPUs utilized          
    21,592,044      cycles                    #    1.596 GHz                    
    80,073,676      instructions              #    3.71  insns per cycle        
    60,144,749      uops_executed_thread      # 4444.487 M/sec                  
    80,162,360      uops_issued_any           # 5923.718 M/sec                  
    80,104,978      uops_retired_retire_slots # 5919.478 M/sec                  

   0.013997088 seconds time elapsed

./uop-test x x的效果统计信息:

     16.672198      task-clock (msec)         #    0.981 CPUs utilized          
    27,056,453      cycles                    #    1.623 GHz                    
    80,083,140      instructions              #    2.96  insns per cycle        
    60,164,049      uops_executed_thread      # 3608.645 M/sec                  
   100,187,390      uops_issued_any           # 6009.249 M/sec                  
   100,118,409      uops_retired_retire_slots # 6005.112 M/sec                  

   0.016997874 seconds time elapsed

我没有在Skylake上找到任何UOPS_RETIRED_ANY指令,只有那个显然是融合域的“退役老虎机”。

最终测试(uop-test x x)是彼得建议使用与RIP相关的cmp即时的变体,其已知不会被微观化:

.loop_riprel
    cmp dword [rel mydata], 1
    cmp dword [rel mydata], 2
    dec ecx
    nop
    nop
    nop
    nop
    jg .loop_riprel

结果表明,每个周期额外的2个uop由uops发出和退出的计数器拾取(因此测试可以区分融合发生,而不是)。

欢迎对其他架构进行更多测试!您可以找到代码(从上面的Peter复制)in github

[1] ......也许其他一些架构介于Skylake和Sandybridge之间,因为Peter只测试了SB而我只测试了SKL。

答案 1 :(得分:5)

没有uop缓存的旧版Intel处理器可以进行融合,因此这可能是uop缓存的一个缺点。我现在没有时间对此进行测试,但下次更新test scripts时,我会为uop fusion添加测试。你试过FMA指令吗?它们是唯一允许在未融合uop中使用3个输入依赖项的指令。

答案 2 :(得分:5)

我现在已经审查了英特尔Sandy Bridge,Ivy Bridge,Haswell和Broadwell的测试结果。我还没有访问过Skylake的测试。结果是:

  • 具有双寄存器寻址和三个输入依赖关系的指令正好融合。只要它们包含不超过32位的数据(或2 * 16位),它们在微操作高速缓存中只占用一个条目。
  • 使用Haswell和Broadwell上的融合乘法和加法指令,可以制作具有四个输入依赖关系的指令。这些指令仍然融合到一个微操作中,并且只在微操作缓存中占用一个条目。
  • 超过32位数据的指令,例如32位地址和8位立即数据仍然可以融合,但在微操作高速缓存中使用两个条目(除非32位可以压缩为16位有符号整数)
  • rip-relative寻址和立即常量的指令不会融合,即使偏移和立即常量都非常小。
  • 所测试的四台机器上的所有结果都相同。
  • 使用我自己的测试程序进行测试,使用足够小的环路上的性能监视计数器来适应微操作缓存。

您的结果可能是由于其他因素造成的。我没有尝试使用IACA。