TL:DR:使用 -march=skylake-avx512 编译,让编译器使用 EVEX 前缀访问 ymm16-31,这样它就可以(希望)为具有 17 个 __m256 值的代码生成更好的 asm 一次“活”。
-march=skylake-avx512 包括-mavx512vl
例如,skylake 架构有 1 或 2 个 AVX-512 fma 单元。这个数字是否也会改变可用的寄存器总数?
不,所有 Skylake CPU 中的物理寄存器文件大小相同,无论存在多少 FMA 执行单元。这些东西是完全正交的。
架构 YMM 寄存器的数量对于 64 位 AVX2 为 16,对于 64 位 AVX512VL 为 32。在 32 位代码中,总是只有 8 个向量寄存器可用,即使是 AVX512。 (所以 32 位对于大多数高性能计算来说已经过时了。)
使用 AVX512VL1 + 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 版本。
如果我编写一个 nbody 算法,每次体体计算使用 17 个寄存器,第 17 个寄存器是否可以间接映射(寄存器重命名硬件)
不,这不是 CPU 和机器代码的工作方式。 在机器代码中,只有一个 4 位(不使用 AVX512-only 编码)或 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 前缀是现有指令的无效编码,翻转那些额外的寄存器编号位会使它们解码为 这些旧指令的有效编码而不是前缀。)
寄存器重命名允许重复使用相同的架构寄存器以获得不同的值,而不会产生任何错误的依赖性。即它avoids WAR and WAW hazards;它是使乱序执行工作的“魔法”的一部分。在考虑 ILP 和乱序执行时,它有助于保持更多的价值,但它不帮助您在简单的程序执行顺序中的任何时候在架构寄存器中获得更多的值。 p>
比如下面的循环只需要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 上,它会成为瓶颈。直到本次迭代中的vmovaps 读取该值后,下一次迭代才能写入 ymm0。
但在无序 CPU 上,多个迭代同时进行,每次对 ymm0 的写入重命名为写入不同的物理寄存器。忽略前端瓶颈(假设我们展开),CPU 可以保持足够的迭代进行,以使 FMA 单元饱和,每个时钟使用 2 个 addps/mulps uops,使用大约 8 个物理寄存器。 (或者更多,因为直到退休后才能真正释放它们,而不是在最后一个微指令读取该值后立即释放)。
有限的物理寄存器文件大小can be the limit on the out-of-order windows size, instead of the ROB or scheduler size。
(基于this result,我们曾一度认为 Skylake-AVX512 使用 2 个 PRF 条目作为 ZMM 寄存器,但后来更详细的实验表明,AVX512 模式可以启动更宽的 PRF 或更高的通道以补充现有PRF,所以 AVX512 模式下的 SKX 仍然具有与 256 位物理寄存器相同数量的 512 位物理寄存器。请参阅discussion between @BeeOnRope and @Mysticial。我认为在某处有更好的实验 + 结果写,但我不能找到它 ATM。)
相关:Why does mulss take only 3 cycles on Haswell, different from Agner's instruction tables? (Unrolling FP loops with multiple accumulators)(回答:它没有;OP 对寄存器重用感到困惑。我的回答详细解释了许多关于多个向量累加器的有趣性能实验。)