【问题标题】:When source registers in avx instruction can be reusedavx指令中的源寄存器何时可以重用
【发布时间】:2021-11-28 04:36:19
【问题描述】:

avx指令中用作源的寄存器在指令开始处理后何时可以重用?

例如:我想使用 vgatherdps 指令,它消耗两个 ymm 寄存器,其中一个是位移索引。我意识到vgatherdps 需要花费大量时间来收集数据,因为数据的局部性很差。

在指令执行期间是否保留位移索引寄存器,或者我可以在后续指令中重复使用它而不挂起流水线?

【问题讨论】:

  • 我的印象是,所有输入寄存器在被消耗后都可以立即使用,因为所有输入都被复制到内部寄存器/触发器,它们通过固定的硬件管道传输。即使没有乱序执行也会出现这种情况,它将 ISA 中为数不多的外部可用寄存器映射到内部可用的更大的寄存器库。
  • @AkiSuihkonen:是的,通常是这样。执行单元获取输入寄存器的副本,即使它是 SIMD 向量,也不会返回查阅架构寄存器。所以是的,即使是有序管道也可以触发聚集并在下一条指令中写入索引。 (尽管聚集故障模型的部分进展意味着有序管道必须验证索引的所有 mask=1 元素的无故障,然后再继续让后面的指令开始。但它仍然不会到期到索引上的 WAR(读后写)危险。)

标签: assembly cpu-architecture simd avx micro-optimization


【解决方案1】:

所有带有 AVX 的 x86 CPU 都会通过寄存器重命名来无序执行以隐藏 Write-After-Write 和 Write-After-Read hazards。见

您永远不必担心由于执行读取或写入前一个值的缓慢指令而导致对寄存器的只写访问停止。(乱序执行有其限制, number of physical register-file entries 是其中之一,但这是与 WAR / WAW 危害不同的因素。)

寄存器重命名的全部意义在于使同一寄存器的新(独立)使用像使用不同寄存器一样执行,从而允许 CPU exploit the instruction-level parallelism

例如,vmovdqa ymm2, [rdi] 不关心之前的指令读取或写入 ymm2(或其 xmm2 低半部分); vmovdqa 的目的地始终是只写的。


既然你提到了聚集,vgatherdps 本身在其目的地不是只写的;它根据掩码向量进行合并。所以如果你在一个循环中重复地收集到同一个寄存器(比如ymm0),你可能想要vpxor xmm0,xmm0,xmm0来打破依赖关系。

但您可能不需要;在 Intel CPU 上,即使读写目标寄存器还没有“准备好”作为输入,收集元素的实际负载也可以开始。 https://uops.info/measured Skylake 上从操作数 1 到操作数 1 的延迟时间为 1 个周期。 (至少当掩码为全一时;对于非故障情况,这可能是特殊情况)。

所以vgatherdps ymm0, [rdi+ymm5*4], ymm1 可以在ymm0 准备好之后的循环中写入ymm0(如果ymm5ymm1 以及指向的内存在22 个周期前准备好)。 (收集吞吐量比这更糟糕;他们通过使用 10x vshufpd ymm0, ymm0, ymm0, 0 之类的指令链来衡量这一点,正如您在该链接中的实验 2 和 3 中看到的那样。)

但是,例如,Zen3 的情况就不那么好了。 vgatherdps ymm 在Zen 3 has latency from operand 1 -> 1 of 8 cycles。但这仍然比索引向量就绪 -> 目标向量就绪的 28 个周期延迟要短得多。 (2 -> 1)

(对于掩码向量设置为全1的正常聚集,您将使用vpcmpeqd ymm1, ymm1, ymm1。它被识别为独立于先前的值,就像一个异或归零习语,所以它甚至算作只写尽管您使用的指令看起来像是实际上会读取和比较。这意味着您已经破坏了涉及掩码向量的 dep 链。有趣的是,在 Skylake 上,如果您 ,则从掩码输入到输出的周期延迟为 0做 有意避免破坏依赖关系。请参阅3->1 section on the uops.info Skylake latency page。大概会收集掩码的 vpxor-zeroing 之类的工作,只有在元素上存在页面错误(或其他错误)时才会有所不同。)

【讨论】:

    【解决方案2】:

    您可以在下一条指令中将寄存器用于不同的目的。与 MIPS 等架构不同,x86 具有互锁的流水线阶段,CPU 确保后面的指令不会影响前面的指令。

    【讨论】:

    • 是的,我知道后面的指令不会影响前面的指令。但它是否会等到上一条指令完成。或者位移索引寄存器被锁在AVX内部模块中,可以立即再次使用?
    • @Yuriy 是否必须等待上一条指令完成取决于您拥有的模型处理器。如果您有一个带有寄存器重命名的处理器,它不会。如果您有一个没有寄存器重命名的处理器,它可能需要等待,但仍然不太可能。
    • 没有任何带有 AVX、AFAIK 的有序 x86 CPU。 (除非 Knight's Corner Xeon Phi 有 AVX;它是一个 P54C,带有 AVX-512 的 512 位 SIMD 祖先,所以可能没有,而且几乎不相关。) Silvermont 不对 SIMD 执行 OoO 执行(仅标量整数) ,但也没有 AVX。 (直到后来的模型,如 Alder Lake 中的 GraceMont,它们确实具有 OoO 执行器)。这个答案是正确的,但不是很有用,IMO。问题不在于正确性,而在于性能(但是基于应用有序管道的想法)。
    • @PeterCordes 非英特尔处理器呢?但是,是的,我的观点更多的是技术性。
    • 我故意说的是 x86,而不是 Intel。我唯一不确定的是英特尔。 AMD 的低功耗 Jaguar 具有乱序功能(Bobcat 也是如此,但它没有 AVX)。他们的低端 Geode 没有/没有 AVX,甚至没有 SSE。 Via Nano 系列是 OoO。当然,自 AVX 出现十多年以来,来自 AMD 和 Intel 的主流 CPU 就一直在积极地进行 OoO 执行。 (重新发布评论以修复语法)。此外,英特尔 Godmont 和后来的英特尔完全是 OoO 执行官,因此 Silvermont 系列的变化早在他们将 AVX 添加到该系列之前就发生了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-26
    • 2019-01-02
    • 2016-11-22
    • 1970-01-01
    相关资源
    最近更新 更多