什么是CPU中的错误依赖?

问题描述 投票:0回答:1

有人可以帮我理解“虚假依赖”是什么意思吗?

我的教授刚刚在这张幻灯片中解释了为什么我们不能在命令 1 之前运行命令 3,但为什么后来他称其为“False”?

enter image description here

pipeline cpu cpu-architecture intel cpu-hazard
1个回答
2
投票

它是“假”,因为后面的指令实际上不需要前面指令的数据。唯一的冲突是找到放置结果的地方。就像幻灯片所说,“不是真正的数据依赖”;只有 RAW 危险才是真正的依赖关系。

如果CPU发明了一个临时位置来放置结果,直到架构寄存器可用为止,它可以独立执行后面的指令。 必须等待该寄存器准备就绪是可以避免的,因此它不是真正的依赖关系,而是错误的。

寄存器重命名通常可以避免 WAR 和 WAW 危险,但特殊情况除外,即 CPU 将指令视为具有来自寄存器的输入,即使结果不依赖于寄存器中的任何位。

既然您标记了此 [intel],即使您的幻灯片不是 x86 asm,也许您更喜欢 x86 示例:

  • 为什么 mulss 在 Haswell 上只需要 3 个周期,与 Agner 的指令表不同? (使用多个累加器展开 FP 循环) - 使用像
    movss
    这样的只写指令写入相同的寄存器会打破对先前值的依赖,因为执行 OoO exec 的 x86 CPU 也会执行寄存器重命名。在矢量点积中保持多个
    vfmadd
    指令运行的一种方法是使用多个寄存器来保存总和。
  • 为什么打破 LZCNT 的“输出依赖”很重要? -
    lzcnt eax, edx
    对于 EAX 来说应该是只写的,但是 Intel Haswell 和 Broadwell 有一个 假输出依赖,像 bsr eax, edx
     那样调度它如果 EDX 为零,则读取 EAX。
  • 用 64 位替换 32 位循环计数器会在 Intel CPU 上使用 _mm_popcnt_u64 引入疯狂的性能偏差同样的问题,但对于 popcnt
    ,在 Ice Lake 之前对 Sandybridge 系列的错误(输出)依赖。有趣的是,它与 
    lzcnt / bsr
     / 
    tzcnt
     / 
    bsf
     在同一执行单元
    上运行。
  • 为什么 GCC 不使用部分寄存器?
  • - 在许多微架构上写入部分寄存器算作完整寄存器的读取-修改-写入,例如mov di, 123 的调度方式与
    add edi, 123
    类似,与
    mov
    到 32 位或 64 位寄存器不同,它们都会
     覆盖整个寄存器以避免错误依赖
    ,而无需进行混乱的部分寄存器重命名。
  • 对 Intel Sandybridge 系列 CPU 中的管道进行去优化
  • - WAW 和 WAR 错误依赖关系不会在 SnB 系列上停止,对同一内存位置的独立写入也不会停止。
© www.soinside.com 2019 - 2024. All rights reserved.