Neoverse N1 中 lsl >4 的 add 流程

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

我有一个关于 Neoverse N1 中添加与移位(adds x3, x4, x5, lsl #32)使用的管道的问题,特别是“adds x3, x4, x5, lsl #32”。

根据 Neoverse N1 软件优化(https://developer.arm.com/documentation/pjdoc466751330-9707/latest/),该指令应该使用 M 管道。

…但是在 Graviton 2(即 Neoverse N1)上运行一些实验似乎表明它似乎并没有这样做。

为了检查它,我编写了一个使 M 管道饱和的代码,如下所示:

.rep 1000
    mul x7, x8, x9
.endr

我可以观察到平均时钟是3.117,这似乎与MADD的描述一致,很好。

如果我像这样添加‘adds x3, x4, x5, lsl #32’,#循环必须增加,因为M管道已经饱和了:

.rep 1000
    mul x7, x8, x9
    adds x3, x4, x5, lsl #32
.endr

但是,观察到的 # 个时钟仍然是 3.13,这意味着

mul
adds
可以并行运行。

怀疑adds指令实际上使用的是“I”管道。这个实验间接表明:

.rep 1000
    add x1, x0, x0; add x1, x0, x0; add x1, x0, x0 // Three adds: saturates I pipeline
.endr

平均时钟为1.14

.rep 1000
    add x1, x0, x0; add x1, x0, x0; add x1, x0, x0
    adds x2, x3, x4, lsl #32
.endr

平均时钟为1.51,增加!

assembly arm cpu-architecture arm64
1个回答
0
投票

显然它只能每 3 个周期启动一个新的 64 位

mul x7, x8, x9
(列出吞吐量 1/3),但您发现它并不能阻止该管道在其他两个周期之一上启动更简单的操作。

可能有一个单独的执行单元用于移位和加法,因此当脚注说“4. X 形式乘法累加”时,乘法器管道会停顿 2 个额外周期。显然,它们指的是实际的乘法执行单元,而不是同一端口上具有不同延迟的其他执行单元。手册没有这么说(明确或根本没有),但这是有道理的。

我想知道

lsl #32
的班次计数是否在某种程度上很特殊;也许尝试
lsl #27
或使用
asr #27
,一些不是半个寄存器的奇数。或者使用寄存器中的移位计数。但如果
adds x3, x4, x5, lsl #32
可以在三个 I 端口中的任何一个上运行,您会看到它自己的 3/时钟吞吐量。


看文档2.2节的图:整数指令总共只有3个管道; 单周期 I 管道之一也是整数多周期管道,因此预计

adds x2, x3, x4, lsl #32
会与未移位的普通
add
竞争吞吐量。

M 不是与 I 分离,它是对三个 I 管道之一的限制。 这就像 Haswell 之前的 Intel CPU。三个整数执行端口 p0、p1 和 p5,但只有其中一个 (p1) 能够运行多周期延迟整数微指令,例如

imul
popcnt
。将 uop 列为
p015
p1
(如 Agner Fog 的指令表或 https://uops.info/)比“I”与“M”更清楚,但这是同一件事。除此之外,Intel CPU 在这些相同的端口上也有 SIMD 和分支执行单元,而 Neoverse 将它们放在单独的管道上,就像 AMD 对 SIMD 所做的那样。

© www.soinside.com 2019 - 2024. All rights reserved.