You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从指令流水线视角解析:数据依赖指令为何出现两种阻塞情况?

数据依赖指令的阻塞问题:Cortex-A76上两段FMLA代码的执行差异

核心结论

存在数据依赖的相邻指令并非一定会相互阻塞,是否阻塞取决于依赖类型、处理器流水线特性以及指令间的间隔/可用的无关指令。结合你给出的两段代码和Cortex-A76的特性,具体原因如下:

第一段代码:无阻塞的原因

先看第一段代码的依赖关系:

.loop1:
    fmla v2.4s, v0.4s, v1.4s  // 写v2 → 后续v4依赖v2
    fmla v3.4s, v0.4s, v1.4s  // 写v3 → 后续v5依赖v3
    subs x0, x0, #1
    fmla v4.4s, v0.4s, v2.4s  // 读v2(依赖第一条FMLA)
    fmla v5.4s, v0.4s, v3.4s  // 读v3(依赖第二条FMLA)
    fmla v6.4s, v0.4s, v4.4s  // 读v4(依赖第四条FMLA)
    fmla v7.4s, v0.4s, v5.4s  // 读v5(依赖第五条FMLA)
    fmla v8.4s, v0.4s, v6.4s  // 读v6(依赖第六条FMLA)
    fmla v9.4s, v0.4s, v7.4s  // 读v7(依赖第七条FMLA)
    bne .loop1
  1. 依赖间隔足够,延迟被隐藏
    Cortex-A76中fmla指令的延迟为4,指指令发射后需4个周期生成可用结果。但第一段代码里,每个写寄存器的fmla和读它的fmla之间,间隔了至少2条无关指令(比如写v2的指令1到读v2的指令4,中间有指令2、3)。同时处理器支持乱序执行和超标量发射,可以在等待v2结果的间隙,先执行其他不依赖v2的指令,完全填满流水线,不会出现停顿。

  2. 独立依赖链并行执行
    代码包含两条完全独立的依赖链:v2→v4→v6→v8 和 v3→v5→v7→v9,链间无数据依赖,Cortex-A76的FP单元可同时调度两条链的指令并行执行,进一步避免阻塞。

第二段代码:出现阻塞的原因

修改后的代码引入了循环携带的依赖:

.loop1:
    fmla v2.4s, v0.4s, v8.4s  // 读v8(依赖上一次循环的最后一条FMLA)
    fmla v3.4s, v0.4s, v9.4s  // 读v9(依赖上一次循环的倒数第二条FMLA)
    subs x0, x0, #1
    fmla v4.4s, v0.4s, v2.4s
    fmla v5.4s, v0.4s, v3.4s
    fmla v6.4s, v0.4s, v4.4s
    fmla v7.4s, v0.4s, v5.4s
    fmla v8.4s, v0.4s, v6.4s  // 写v8(供下一次循环的第一条指令使用)
    fmla v9.4s, v0.4s, v7.4s  // 写v9(供下一次循环的第二条指令使用)
    bne .loop1

这里的关键是:当前循环的前两条fmla指令需要读取v8和v9,而这两个寄存器的值是上一次循环的最后两条指令才生成的,形成了跨迭代的依赖链:上一次循环的v8写指令 → 当前循环的v2读指令。

由于fmla延迟为4,当前循环的第一条指令必须等待上一次循环的最后一条fmla完成(4个周期)才能执行,导致每个循环迭代都要等待4个周期的停顿,无法利用乱序执行或并行调度隐藏延迟。最终执行时间t2变成t1的4倍,完全符合延迟带来的阻塞效果。

总结

  • 数据依赖指令是否阻塞,核心看依赖是否会导致流水线无法填充:若依赖间有足够无关指令,处理器可通过乱序执行隐藏延迟,就不会阻塞;
  • 循环携带的依赖是最易导致严重阻塞的场景,它会让迭代之间必须串行等待,无法利用并行或乱序执行的优势。

内容的提问来源于stack exchange,提问作者zhiyujiang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 17:56:09