有人可以帮我理解“虚假依赖”是什么意思吗?
我的教授刚刚在这张幻灯片中解释了为什么我们不能在命令 1 之前运行命令 3,但为什么后来他称其为“False”?
它是“假”,因为后面的指令实际上不需要前面指令的数据。唯一的冲突是找到放置结果的地方。就像幻灯片所说,“不是真正的数据依赖”;只有 RAW 危险才是真正的依赖关系。
如果CPU发明了一个临时位置来放置结果,直到架构寄存器可用为止,它可以独立执行后面的指令。 必须等待该寄存器准备就绪是可以避免的,因此它不是真正的依赖关系,而是错误的。
寄存器重命名通常可以避免 WAR 和 WAW 危险,但特殊情况除外,即 CPU 将指令视为具有来自寄存器的输入,即使结果不依赖于寄存器中的任何位。
既然您标记了此 [intel],即使您的幻灯片不是 x86 asm,也许您更喜欢 x86 示例:
movss
这样的只写指令写入相同的寄存器会打破对先前值的依赖,因为执行 OoO exec 的 x86 CPU 也会执行寄存器重命名。在矢量点积中保持多个 vfmadd
指令运行的一种方法是使用多个寄存器来保存总和。lzcnt eax, edx
对于 EAX 来说应该是只写的,但是 Intel Haswell 和 Broadwell 有一个 假输出依赖,像 bsr eax, edx
那样调度它如果 EDX 为零,则读取 EAX。
popcnt
,在 Ice Lake 之前对 Sandybridge 系列的错误(输出)依赖。有趣的是,它与
lzcnt
/ bsr
/
tzcnt
/
bsf
在同一执行单元上运行。
mov di, 123
的调度方式与 add edi, 123
类似,与 mov
到 32 位或 64 位寄存器不同,它们都会 覆盖整个寄存器以避免错误依赖,而无需进行混乱的部分寄存器重命名。