Performance 依赖链分析

Performance 依赖链分析,performance,assembly,x86,cpu-architecture,micro-optimization,Performance,Assembly,X86,Cpu Architecture,Micro Optimization,第12.7节:循环示例。讨论示例代码的段落之一: […]奔腾M的分析:。。。13个UOP,每个时钟3个=每4.33c退役时间一次迭代 循环中有一个依赖链。延迟时间为:2秒 内存读取,5表示乘法,3表示减法,3表示内存 写入,总共13个时钟周期。这是我的三倍 退休时间,但它不是循环携带依赖,因为 每次迭代的结果都保存到内存中,不会在中重复使用 下一次迭代。无序执行机制及其应用 流水线使得每次计算都可以在之前开始 前面的计算完成了。唯一的循环 依赖链是addeax,16,延迟时间仅为1 我无法理解为

第12.7节:循环示例。讨论示例代码的段落之一:

[…]奔腾M的分析:。。。13个UOP,每个时钟3个=每4.33c退役时间一次迭代

循环中有一个依赖链。延迟时间为:2秒 内存读取,5表示乘法,3表示减法,3表示内存 写入,总共13个时钟周期。这是我的三倍 退休时间,但它不是循环携带依赖,因为 每次迭代的结果都保存到内存中,不会在中重复使用 下一次迭代。无序执行机制及其应用 流水线使得每次计算都可以在之前开始 前面的计算完成了。唯一的循环 依赖链是
addeax,16
,延迟时间仅为1

我无法理解为什么依赖链不能增加整个吞吐量。我知道找到最严重的瓶颈才是最重要的。在考虑依赖链之前确定的最严重瓶颈是融合域uop吞吐量,每次迭代4.33个周期。我无法理解为什么依赖链不是比这更大的瓶颈

  • 我看到作者解释了它与无序执行和管道连接,但我看不到它。我的意思是,虽然只有乘法会导致延迟5个周期,所以只有这个值大于4个周期

  • 我也无法理解为什么作者不关心这里的依赖关系:
    添加eax,16->cmp eax,ecx->jl L1
    毕竟,加法必须在
    cmp
    之前执行,而
    cmp
    必须在
    jl
    之前执行


  • PS:后面的段落将奔腾M的最大瓶颈确定为解码,将其限制为每6c迭代一次,因为128b矢量运算每段解码两个UOP。请参阅《Agner Fog指南》了解其余的分析,以及Core2、FMA4推土机和Sandybridge的分析+调整

  • mul不属于循环携带的依赖链的一部分,因此可以同时从飞行中的多次迭代中获得
    mulpd
    INSN。这里的问题根本不是单个指令的延迟,而是依赖链。每个迭代都有一个单独的13c依赖链,包括load、mulpd、SUBSPD和store。无序执行允许来自多个迭代的UOP同时运行

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

    相比之下,
    cmov
    是一个数据依赖项,而不是控制依赖项,因此无分支循环往往具有循环携带的依赖链。如果分支预测良好,则这往往比分支慢

    每个循环迭代都有一个独立的
    cmp
    /
    jl
    依赖链,就像FP依赖链一样


  • 我无法理解为什么依赖链不能增加整个吞吐量


    我不知道这句话的意思。我想我能猜出你所有其他混淆的词和短语。(例如,“依赖链”而不是“依赖链”。)看看我对你的问题所做的编辑;其中一些可能也有助于您的理解。

    比较/分支对将被预测,因此它实际上不起作用。除此之外,我不确定你在问什么,你能链接Agner的文档并说明你引用的章节和示例吗?谢谢:)。首先,您的观点是:好的,很明显,多个迭代可以同时进行。但是,当只涉及到一个迭代时,特别的迭代。为什么mulpd(5个周期)的延迟无关紧要?毕竟,
    subpd xmm0,xmm1
    后面必须跟
    mulpd xmm1,xmm2
    (在一个迭代的依赖链中)。对不起,我的英语,我知道它可能有问题。2.Agner Fog说,
    添加eax,16
    是循环传输的,它需要1个周期(延迟)。@Gilgamesz:2。没错
    add
    ->
    add
    是循环携带的依赖链,而不是
    add->cmp->jl->add
    。re:第一点:你能更具体地解释一下为什么你认为它很重要吗?我们计算的是吞吐量,而不是单个迭代的延迟。只要无序的insn调度程序和重新排序缓冲区足够大,以暴露迭代之间的并行性,迭代中dep链的延迟就无关紧要。(一个很长的dep链需要一个大的调度程序和ROB)。dep链中任何特定指令的延迟都是不相关的。好吧,@Peter Cordes这是有道理的。非常感谢。:)
    ## 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