0

来自Agner Fog's "Optimizing Assembly" guide,第12.7节:循环示例。其中一段讨论的示例代码:依赖链分析

[...]奔腾M分析:... 13 uops在每时钟3 =一个迭代每4.33c退休时间。

循环中有一个依赖链。等待时间为:对于 存储器读取有2个,对于乘法有5个,对于相减有3个,对于存储器 写有3个,总计13个时钟周期。这是退休时间的三倍,但它不是循环携带的依赖关系,因为每次迭代的结果都保存到内存中,并且在下一次迭代中不会重复使用 。无序执行机制和 流水线使得每个计算可以在前面的计算完成之前 之前开始。唯一的循环进行 依赖链是add eax,16拥有的只有1

## Example 12.6b. DAXPY algorithm, 32-bit mode 
[...] ; not shown: initialize some regs before the loop 
L1: 
    movapd xmm1, [esi+eax] ; X[i], X[i+1] 
    mulpd xmm1, xmm2  ; X[i] * DA, X[i+1] * DA 
    movapd xmm0, [edi+eax] ; Y[i], Y[i+1] 
    subpd xmm0, xmm1  ; Y[i]-X[i]*DA, Y[i+1]-X[i+1]*DA 
    movapd [edi+eax], xmm0 ; Store result 
    add eax, 16    ; Add size of two elements to index 
    cmp eax, ecx    ; Compare with n*8 
    jl L1     ; Loop back 

等待时间我不明白为什么依赖链不增加整体吞吐量。我知道只有找到最坏的瓶颈才是重要的。在考虑依赖链之前确定的最糟糕的瓶颈是融合域uop吞吐量,每次迭代4.33个周期。我不明白为什么依赖链不是比那更大的瓶颈。

  1. 我看到作者解释说它与无序执行和流水线连接,但我看不到它。不过,我的意思是,只有乘法会导致延迟5个周期,所以只有这个值大于4个周期。

  2. 我也无法理解为什么笔者不关心的依赖性在这里: add eax, 16 -> cmp eax, ecx -> jl L1 毕竟,之前cmpcmp必须jl之前执行除了必须执行。


PS:后面的段落标识最大的瓶颈为奔腾M作为解码,将其限制到每6C一次迭代,因为128B矢量OPS进行解码,以每两个微指令。请参阅Agner Fog的指南以了解其他分析,以及Core2,FMA4推土机和Sandybridge的分析+调整。

+0

比较/分支对将被预测,因此它不会真正计数。除此之外,我不知道你在问什么 – harold

+1

你能否把Agner的文档链接起来,并陈述你所引用的部分和范例? –

回答

2
  1. 的MUL不是循环搬运依赖关系链的一部分,因此可以有从多个迭代mulpd的insn在飞行中一次。单条指令的延迟根本就不是问题,它依赖于链条。每次迭代都有一个单独的13c依赖链的load,mulpd,subpd,store。无序执行是允许来自多个迭代的uops一次处于运行状态。

  2. 在每个迭代的cmp/jl取决于add从迭代,但在接下来的迭代中add不依赖于cmp。推测性执行和分支预测意味着控制依赖性(条件分支和间接跳转/调用)不是数据依赖链的一部分。这就是为什么来自一次迭代的指令可以在来自前一次迭代的jl退役之前开始运行。

    通过比较,cmov数据依赖性,而不是控制依赖关系,因此无分支循环倾向于具有循环承载的依赖关系链。如果分支预测得好,这往往比分支慢。

    与FP依赖关系链一样,每个循环迭代都有一个独立的依赖关系链,其中包括独立的cmp/jl依赖关系链。


我不明白为什么依赖链不增加整体吞吐量。

我不知道这句话的意思。我想我能弄清楚所有其他的混合词和措辞。 (例如,“链依赖”而不是“依赖链”)。看看我对你的问题的编辑;其中一些也可能有助于你的理解。

+0

谢谢:)。首先你的观点:好的,很明显,多次迭代可以同时进行。但是,当涉及到只有一次迭代时,特定的迭代。为什么mulpd的延迟(5个周期)无关紧要?毕竟,'subpd xmm0,xmm1'必须跟着'mulpd xmm1,xmm2'(在一个迭代中的一个依赖链中)。对不起,我的英文,我知道它可能有问题。 2. Agner Fog说'add eax,16'是循环传送的,它需要1个周期(等待时间)。 – Gilgamesz

+1

@Gilgamesz:2.没错。 'add' - >'add'是循环携带的依赖链,不是'add - > cmp - > jl - > add''。 –

+1

回复:第一点:你能更具体地说明你为什么认为它*很重要吗?我们正在计算吞吐量,而不是单次迭代的延迟。只要无序insn调度程序和ReOrder缓冲区足够大以暴露迭代之间的并行性,迭代中dep链的延迟是无关紧要的。 (一个真正长的dep链需要一个大的调度器和ROB)。该dep链中任何特定指令的延迟甚至不太重要。 –