如何解读uops.info?

Ell*_*sky 4 x86 assembly x86-64 simd avx512

我在 uops.info 上查找了指令VMOVDQA,试图找出 (1) 延迟是多少,以及 (2) 我可以执行多少个并发负载?

\n

我在解释结果时遇到困难(下面的屏幕截图,上面也有链接):

\n
    \n
  • 该指令的不同变体意味着什么?例如A64 Z (ZMM, K, ZMM)vs A64 (ZMM, K, ZMM)?\n
      \n
    • 它似乎为参数提供了不同的类型,也许表明哪些参数在寄存器中?但我不知道如何阅读该符号。
    • \n
    \n
  • \n
  • 为什么有时有两个延迟数字,例如[\xe2\x89\xa410;\xe2\x89\xa411]?这是否表示延迟范围,如果是,我可以计算出我的用例的确切延迟吗?
  • \n
  • 我应该如何解释吞吐量 (TP) 列?
  • \n
\n

非常感谢任何对此的指示!

\n

uops.info 的屏幕截图

\n

Pet*_*des 5

如果仅运行该指令的一大块,则吞吐量是倒数吞吐量。(或者使用破坏依赖性的指令来处理类似adc或div由于隐式寄存器输入/输出(尤其是标志)而无法使连续执行不具有数据依赖性的情况)。这0.5意味着它可以每 0.5 个周期运行一次,即 2 个/时钟,正如我们所知道的具有 2 个负载端口的 CPU 所预期的那样。

\n
\n

为什么有时有两个数字表示延迟,例如[\xe2\x89\xa410;\xe2\x89\xa411]?

\n
\n

另请参阅作为单个指令的延迟,多个值或范围意味着什么?以load+ALU ALU指令为例。(我忘记了它有多接近重复,直到我写完这个答案的其余部分才开始寻找它。)

\n

通常这表明从不同输入到输出的延迟可能不同。例如,合并屏蔽加载必须合并到目标中,以便这是一个输入,而加载地址是另一个输入(通过整数寄存器)。内存中最近存储的数据是第三个输入(存储转发延迟)。

\n

对于向量加载使用延迟等情况,其中加载结果与地址寄存器位于不同的域中,uops.info 创建一个依赖链,其中包含涉及movd或vmovq rax, xmm0将加载结果耦合回另一个加载的地址的指令序列。很难单独确定每个部分的延迟,因此 IIRC 他们假设链中的每个其他指令至少有 1 个周期,并将被测试指令的延迟显示为<= N,其中 N + dep 链的其余部分加起来就是测试代码每次迭代的总周期。

\n

查看这些结果之一的详细信息页面,其中显示了用于测量它的测试序列。表中的每个数字也是一个链接。这些详细信息页面告诉您哪个操作数是哪个,并细分从每个输入到每个输出的延迟。让我们看一下零掩码vmovdqa64512 位负载 ( VMOVDQA64_Z (ZMM, K, M512)),他们在 asm 中使用 进行了测试vmovdqa64 zmm0{k1}{z},ZMMWORD PTR [r14]。列出的延迟是[1;\xe2\x89\xa49]。

\n

他们将操作数编号为

\n
    \n
  • 1(只写):ZMM 目的地。
  • \n
  • 2(只读):k0..7掩码寄存器
  • \n
  • 3(只读):内存(稍后分为地址与实际内存内容)
  • \n
\n

周期1延迟部分是从掩码寄存器到结果的延迟,“Latency operand 2 \xe2\x86\x92 1: 1”。因此,在加载单元获取数据之前,掩码不必准备好。

\n

这<=9是从地址基址或索引寄存器到最终 ZMM 结果准备就绪的延迟。

\n

显然,在存储/重新加载情况下,存储转发延迟成为瓶颈,“延迟操作数 3 \xe2\x86\x92 1(内存):\xe2\x89\xa46”。他们使用这个序列进行了测试,描述为“链延迟:\xe2\x89\xa56”。 vshufpd zmm已知有 1 个周期延迟,我猜他们只是将商店计算为有 1 个周期延迟?就像我说的,他们只是假设一切都是 1 个周期,尽管将任何延迟分配给存储有点可疑。

\n
Code:\n   0:   62 d1 fd c9 6f 06       vmovdqa64 zmm0{k1}{z},ZMMWORD PTR [r14]\n   6:   62 71 fd 48 c6 e8 00    vshufpd zmm13,zmm0,zmm0,0x0\n   d:   62 51 95 48 c6 ed 00    vshufpd zmm13,zmm13,zmm13,0x0\n  14:   62 51 95 48 c6 ed 00    vshufpd zmm13,zmm13,zmm13,0x0\n  1b:   62 51 95 48 c6 ed 00    vshufpd zmm13,zmm13,zmm13,0x0\n  22:   62 51 95 48 c6 ed 00    vshufpd zmm13,zmm13,zmm13,0x0\n  29:   62 51 fd 48 11 2e       vmovupd ZMMWORD PTR [r14],zmm13\n
Run Code Online (Sandbox Code Playgroud)\n

(对于吞吐量测试,他们多次重复该块以创建展开的循环。但对于延迟测试,他们可能只是在其周围包裹一个正常的循环。nanobench 是开源的,因此您可以检查。)

\n

对于“延迟操作数 3 \xe2\x86\x92 1(地址,基址寄存器):\xe2\x89\xa49”测量,他们说“链延迟:\xe2\x89\xa55”。我们知道一次vmovq r,x/vmovq x,r往返的延迟时间超过 2 个周期,因此vmovq这里的链部分可能超过一个周期。这就是为什么他们高估了加载使用延迟,保守上限为 9 个周期。

\n
   0:   62 d1 fd c9 6f 06       vmovdqa64 zmm0{k1}{z},ZMMWORD PTR [r14]\n   6:   c4 c1 f9 7e c4          vmovq  r12,xmm0\n   b:   4d 31 e6                xor    r14,r12\n   e:   4d 31 e6                xor    r14,r12\n  11:   4d 31 e6                xor    r14,r12\n  14:   4d 31 e6                xor    r14,r12\n
Run Code Online (Sandbox Code Playgroud)\n

他们测量:

\n
\n
    \n
  • 已退役指令:6.0
  • \n
  • 核心周期:14.0
  • \n
  • 参考周期:10.81
  • \n
  • UOPS_EXECUTED.线程:7.0
  • \n
\n
\n

每次迭代总共 14 个周期,因此他们计算出掩码负载所占的 14-5 = 9 个周期。(或者如果链延迟实际上长于 5,则更少。实际上vmovq可能是 3 或 4 个周期,因此 7 或 6 个周期的 SIMD 加载延迟听起来不错。我们知道整数加载使用延迟是 5 个周期,IIRC Intel's优化手册提到 SIMD 负载为 6 或 7 个周期。但是,这个保守的上限 9 是我们纯粹基于测量才能真正确定的,无需外推/猜测。)

\n
\n

AVX-512 指令命名。

\n

“A64”是AVX-512vmovdqa64指令助记符的一部分,当然:查看Intel的asm手册: https: //www.felixcloutier.com/x86/movdqa :vmovdqa32: vmovdqa64。请记住,AVX-512 支持(几乎)每条指令的每元素合并或零掩码,因此偶数movdqa和按位运算需要元素大小。这也是为什么 AVX-512 按位布尔值是vpord/q而不仅仅是vpor (它们可以使用 b/w/d/q 命名 movdqa 元素大小,但是我们有 or vmovdqad,vmovdqaq但我认为我们可以很高兴他们没有。)

\n

幸运的是,a32 与 a64 不会产生任何性能差异,只有当您使用掩码时,结果才会有任何差异,例如 via_mm512_maskz_load_epi32( __mmask16 k, void * sa)与 epi64 仅采用__mmask8. 或者对于较小的向量宽度,仅使用少于 8 位的掩码。

\n

零掩码与合并掩码

\n

op Z (ZMM, K, ZMM)vs op (ZMM, K, ZMM)是零掩码与合并掩码。如果您不知道 AVX-512 掩蔽的工作原理,请阅读相关内容。例如,Kirill Yukhin 的演示幻灯片提供了概述:\n https://en.wikichip.org/w/images/d/d5/Intel_Advanced_Vector_Extensions_2015-2016_Support_in_GNU_Compiler_Collection.pdf

\n

不带屏蔽(无k寄存器)的 Reg-reg vmovdqa 可以是 0 延迟(mov 消除),但使用屏蔽时它始终为 1。

\n

有趣的事实:寄存器重命名k0..k7使用与 MMX/x87 相同的物理寄存器文件空间:https://travisdowns.github.io/blog/2020/05/26/kreg2.html

\n