TL:DR: compile with-march=skylake-avx512
让编译器使用 EVEX 前缀来访问 ymm16-31 以便它可以(希望)为同时具有 17 个__m256
“live”值的代码生成更好的 asm。
-march=skylake-avx512
包括-mavx512vl
例如,skylake 架构有 1 或 2 个 AVX-512 fma 单元。这个数字是否也会改变可用的总寄存器?
不,无论存在多少 FMA 执行单元,所有 Skylake CPU 中的物理寄存器文件大小都相同。这些东西是完全正交的。
架构 YMM 寄存器的数量对于 64 位 AVX2 为 16,对于 64 位 AVX512VL 为 32。在 32 位代码中,总是只有 8 个向量寄存器可用,即使是 AVX512。(因此对于大多数高性能计算来说,32 位已经过时了。)
带有 AVX512VL 1 + AVX2的 YMM16-31 需要更长的 EVEX 编码,但所有操作数都在低 16 位的指令可以使用指令的较短 VEX 前缀 AVX/AVX2 形式。(混合 VEX 和 EVEX 编码没有任何惩罚,因此 VEX 对于代码大小更可取。但如果避免 y/zmm0-y/zmm15,则不需要 VZEROUPPER;legacy-SSE 指令无法触及 xmm16-31所以没有可能的问题。)
同样,这些都与存在的 FMA 执行单元的数量无关。
脚注 1:AVX512F 仅包含大部分指令的 ZMM 版本;大多数 YMM 指令的 EVEX 编码都需要 AVX512VL。仅有 AVX512F 而不是 AVX512VL 的 CPU 是 Xeon Phi、KNL / KNM,现已停产;所有主流 CPU 都支持它们支持的所有 AVX512 指令的 xmm/ymm 版本。
如果我在每个体体计算中使用 17 个寄存器编写一个 nbody 算法,第 17 个寄存器是否可以间接映射(寄存器重命名硬件)
不,这不是 CPU 和机器代码的工作方式。 在机器代码中,只有一个 4 位(不使用仅 AVX512 编码)或 5 位(使用 AVX512 编码)字段来指定指令的寄存器操作数。
如果您的代码需要 17 个向量值一次“活动”,则编译器必须发出指令以溢出/重新加载其中一个,以 x86-64 AVX2 为目标,它在架构上只有 16 个 YMM 寄存器。即它有16 个不同的名称,CPU 可以将它们重命名到其更大的内部寄存器文件中。
如果寄存器重命名解决了整个问题,x86-64 就不会费心将架构寄存器的数量从 8 个整数/8 xmm 增加到 16 个整数/16 xmm。
这就是为什么 AVX512 花费 3 个额外位(dst、src1 和 src2 各 1 个)来允许访问超出 VEX 前缀可以编码的 32 个架构矢量寄存器。(仅在 64 位模式下;32 位模式仍然只有 8 个。在 32 位模式下,VEX 和 EVEX 前缀是现有指令的无效编码,翻转那些额外的寄存器编号位将使它们解码为有效编码那些旧指令而不是作为前缀。)
寄存器重命名允许为不同的值重复使用相同的体系结构寄存器,而不会产生任何错误的依赖性。即它避免了WAR和WAW的危害;它是使乱序执行工作的“魔法”的一部分。在考虑 ILP 和无序执行时,它有助于保持更多的价值,但它并不能帮助您在简单的程序执行顺序中的任何时候在架构寄存器中拥有更多的值。
例如,下面的循环只需要3个架构寄存器,并且每次迭代都是独立的(没有循环携带的依赖,除了指针增量)。
.loop:
vaddps ymm0, ymm1, [rsi] ; ymm0 = ymm1, [src]
vmulps ymm0, ymm0, ymm2 ; ymm0 *= ymm2
vmovaps [rsi+rdx], ymm0 ; dst = src + (dst_start - src_start). Stays micro-fused on Haswell+
add rsi, 32
cmp rsi, rcx ; }while(rsi < end_src)
jb .loop
但是,从 ymm0 的第一次写入到迭代中的最后一次读取有 8 个周期的延迟链(Skylake addps / mulps 各为 4 个周期),在没有寄存器重命名的 CPU 上,它会成为瓶颈。下一次迭代无法写入 ymm0,直到vmovaps
本次迭代中的 读取了该值。
但是在乱序 CPU 上,多个迭代同时进行,每次对 ymm0 的写入都重命名为写入不同的物理寄存器。忽略前端瓶颈(假设我们展开),CPU 可以保持足够的迭代进行,以使 FMA 单元饱和,每个时钟使用 2 个 addps/mulps uops,使用大约 8 个物理寄存器。(或者更多,因为它们实际上直到退休才能被释放,而不仅仅是在最后一个 uop 读取该值时)。
有限的物理寄存器文件大小可以是无序窗口大小的限制,而不是 ROB 或调度程序大小。
(基于此结果,我们曾一度认为 Skylake-AVX512 使用 2 个 PRF 条目作为 ZMM 寄存器,但后来更详细的实验表明,AVX512 模式可以为更宽的 PRF 或更高的通道供电以补充现有的 PRF,因此 SKX在 AVX512 模式下仍然具有与 256 位物理寄存器相同数量的 512 位物理寄存器。请参阅@BeeOnRope 和 @Mysticial 之间的讨论。我认为在某处有更好的实验 + 结果写,但我不能找到它ATM。)
相关:为什么 mulss 在 Haswell 上只需要 3 个周期,与 Agner 的指令表不同?(展开具有多个累加器的 FP 循环)(答案:它没有;OP 对寄存器重用感到困惑。我的回答详细解释了一些关于多个向量累加器的有趣性能实验。)