hus*_*sik 3 x86 cpu-architecture cpu-registers compiler-optimization avx512
假设以AVX2为目标的编译和C++内在函数,如果我每个体体计算使用17个寄存器编写一个nbody算法,那么第17个寄存器可以间接(寄存器重命名硬件)或直接(visual studio编译器,gcc编译器)映射到AVX上-512注册以减少内存依赖关闭?例如,skylake架构有1或2个AVX-512 fma单元.这个数字是否也改变了总寄存器?(具体来说,至强银4114 cpu)
如果这样可行,它是如何工作的?当所有指令都是AVX2或更低时,第一个硬件线程使用每个ZMM向量的前半部分和第二个硬件线程使用每个ZMM向量的后半部分?
编辑:如果在目标机器上进行在线编译会怎样(例如,使用OpenCL)?司机可以为我注册使用吗?
TL:DR:编译时-march=skylake-avx512让编译器使用EVEX前缀来访问ymm16-31,这样它就可以(希望)为具有17个__m256值"live"的代码做出更好的asm .
例如,skylake架构有1或2个AVX-512 fma单元.这个数字是否也改变了总寄存器?
不,无论存在多少个FMA执行单元,所有Skylake CPU中的物理寄存器文件大小都相同.这些事情是完全正交的.
对于64位AVX2,架构YMM寄存器的数量为16,对于64位AVX512VL,则为32.在32位代码中,即使使用AVX512,也始终只有8个矢量寄存器可用.(因此对于大多数高性能计算来说,32位是非常过时的.)
请注意,AVX512F仅包含大多数指令的ZMM版本; 对于大多数YMM指令的EVEX编码,您需要AVX512VL.
使用AVX512VL + AVX2的YMM16-31需要更长的EVEX编码,但是低16的所有操作数的指令可以使用较短的VEX前缀AVX/AVX2形式的指令.(混合VEX和EVEX编码没有任何代价,因此VEX更适合代码大小.但如果你避免使用y/zmm0-y/zmm15,则不需要VZEROUPPER;传统的SSE指令不能触及xmm16-31所以没有可能的问题.)
同样,这些都与FMA执行单元的数量无关.
如果我每个体体计算使用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各一个)来允许访问32个架构向量寄存器(在64位模式下; 32位模式仍然只有8个).
寄存器重命名允许重复使用一个不同的值相同的架构寄存器的,没有任何虚假的依赖.即它避免了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
Run Code Online (Sandbox Code Playgroud)
但是,从第一次写入ymm0到迭代中的最后一次读取(Skylake addps/mulps各为4个周期),有8个周期的延迟链,在没有寄存器重命名的CPU上会出现瓶颈.vmovaps在此迭代中读取该值之前,下一次迭代无法写入ymm0 .
但是在无序CPU上,多次迭代同时进行,每次写入ymm0都会重命名为写入不同的物理寄存器.忽略前端瓶颈(假装我们展开),CPU可以使用大约8个物理寄存器在飞行中保持足够的迭代以使每个时钟2个addps/mulps uop饱和FMA单元.(或者更重要的是,因为它们实际上不能在退休之前被释放,而不是在最后一次uop读取该值之后立即释放).
有限的物理寄存器文件大小可以是无序窗口大小的限制,而不是ROB或调度程序大小.
(基于这个结果,我们想了一会儿Skylake-AVX512使用2个PRF条目作为ZMM寄存器,但后来更详细的实验显示AVX512模式为更宽的PRF或上部通道供电,以补充现有的PRF,因此SKX在AVX512模式下,仍然有与256位物理寄存器相同数量的512位物理寄存器.请参阅@BeeOnRope和@Mysticial之间的讨论.我认为有一个更好的实验记录+结果,但我不能找到ATM.)
相关:为什么mulss在Haswell上只需要3个周期,与Agner的指令表不同?(回答:事实并非如此; OP对寄存器重用感到困惑.我的答案详细解释了一些有关多个向量累加器的有趣性能实验.)
不.如果你的目标是AVX2架构,那么生成的代码必须能够在任何支持 AVX2的CPU 上运行.其中许多不支持AVX-512,因此它们没有您想要使用的额外寄存器.
话虽如此,没有理由不能使用AVX512VL支持(即-mavx512vl在gcc中)编译并使用AVX2内在函数编写代码.在这种情况下,编译器将能够使用附加寄存器,因为它的目标是AVX-512架构,所有这些架构都包含32个[xyz]mm寄存器.