pob*_*oby 9 performance x86 assembly avx micro-optimization
我理解VZEROUPPER在混合SSE和AVX代码时使用很重要,但如果我只使用AVX(和普通的x86-64代码)而不使用任何传统的SSE指令呢?
如果我从不在我的代码中使用单个SSE指令,是否有任何性能原因我需要使用VZEROUPPER?
这假设我没有调用任何外部库(可能使用SSE).
你是正确的,如果你的整个程序不使用任何写V xmm寄存器的非VEX指令,你就不需要vzeroupper避免状态转换惩罚.
请注意,非VEX指令可能潜伏在CRT启动代码和/或动态链接器或其他非常明显的位置.
也就是说,非VEX指令只能在运行时导致一次性惩罚.反之亦然:一条VEX-256指令通常可以使非VEX指令(或仅与该寄存器一起)对于程序的其余部分来说变慢.
有没有惩罚混合VEX和EVEX的时候,所以没有必要使用vzeroupper那里.
在Skylake-AVX512上:vzeroupper或者vzeroall是弄脏ZMM寄存器后恢复max-turbo的唯一方法.
AVX-512指令对周围代码有一个新的非常糟糕的影响:一旦执行了512位指令(除了可能没有写入zmm寄存器的指令),内核进入"上256个脏状态" .在这种状态下,任何后来的标量FP/SSE/AVX指令(使用xmm或ymm regs的任何内容)将在内部扩展到512位.这意味着在发出vzeroupper或vzeroall之前,处理器将被锁定为不高于AVX turbo(所谓的"L1许可证").
与AVX和传统的非VEX SSE(仍然存在于Skylake Xeon上)的早期"脏上128"问题不同,由于频率较低,这将减慢所有代码,但没有"合并uops"或错误依赖或类似的东西:只是将较小的操作有效地视为512位宽,以实现零扩展行为.
关于"写下半部 ......" - 不,这是一个全球状态,只有vzero*让你脱离它.即使你弄脏zmm寄存器但是使用不同的ymm和xmm也会发生这种情况.即使唯一的弄脏指令是一个归零的成语,它也会发生
vpxord zmm0, zmm0, zmm0.但是,对zmm16-31的写入不会发生.
他实际上将所有向量操作扩展到512位的描述并不完全正确,因为他后来证实它不会降低128位和256位指令的吞吐量.但我们知道,当512位uop处于运行状态时,端口1上的向量ALU将被关闭.(因此,通常可通过端口0和1访问的256位FMA单元可以组合成一个512位单元,用于所有FP数学,整数移位和乘法,以及其他一些东西.)
对于仅使用AVX1/AVX2后的max-turbo(包括像Haswell这样的早期CPU):如果一段时间没有使用(有时允许更高的Turbo时钟速度),有机会关闭执行单元的上半部分取决于是否最近使用了YMM指令,而不是上半部是否脏.所以,据我所知,vzeroupper并没有帮助CPU未油门时钟速度越快使用AVX1/AVX2,对于CPU其中max涡轮增压是256位更低了.
这与英特尔的Skylake-AVX512(SKX/Skylake-SP)不同,后者AVX512在某种程度上"拴在一起".
VZEROUPPER可以使上下文切换稍微便宜因为CPU仍然知道ymm-upper状态是干净还是脏.
如果它是干净的,xsaveopt可以更紧凑地写出FPU状态,而根本不存储全零上半部分(只是设置一个说它们是干净的).请注意SSE/AVX的状态转换图中xsave/ xrstor是图片的一部分.
vzeroupper如果您的代码在此之后很长一段时间内不会使用任何256b指令,那么仅需考虑额外的因素,因为理想情况下,在下次使用256位向量之前,您不会进行任何上下文切换/ CPU迁移.
脏的上半部分可能占用物理寄存器,限制了CPU的无序窗口大小以找到指令级并行性.(ROB大小是另一个主要限制因素,但PRF大小可能是瓶颈.)
在AMD CPU上肯定是这样,其中256b操作分为两个128b操作.YMM寄存器在内部处理为两个128位寄存器,例如vmovaps ymm0, ymm1,以零延迟重命名低128,但上半部需要uop.(参见Agner Fog的microarch pdf)
我在第一段中链接的ROB size/PRF size博客文章中的实验表明,FP物理寄存器文件条目在Sandybridge中是256位的. vzeroupper不应该使用AVX/AVX2在主流Intel CPU上释放更多寄存器,只有AVX512具有脏ZMM高256.
Silvermont不支持AVX.它为架构状态使用单独的退出寄存器文件,因此无序PRF仅保存推测执行结果.因此即使它确实支持具有128位半部分的AVX,具有脏上半部分的陈旧YMM寄存器可能不会在重命名寄存器文件中消耗额外空间.
KNL(Knight's Landing/Xeon Phi)专为运行AVX512而设计,因此其FP寄存器文件可能具有512位条目.它基于Silvermont,但核心的SIMD部分是不同的(例如,它可以重新排序FP /向量指令,而Silvermont只能推测性地执行它们,但不能在FP /向量管道中重新排序它们,根据Agner Fog).尽管如此,KNL也可能使用单独的退出寄存器文件,因此即使能够分割512位条目以存储两个256位向量,脏ZMM上层也不会消耗额外空间.这是不太可能的,因为KNL上只有AVX1/AVX2的更大的无序窗口不值得花费晶体管.
vzeroupperKNL比主流Intel CPU慢得多(64位模式下每36个循环一个),所以你可能不想使用,特别是只有微小的上下文切换优势.
在Skylake-AVX512上,证据支持矢量物理寄存器文件为512位宽的结论.高256位可能来自一个单独的物理阵列,只有在ZMM脏的鞋面时才会启动.特别是BeeOnRope发现脏的zmm鞋面会使CPU最大涡轮时钟无限减少,这表明某些东西必须保持通电状态.但是,对zmm16..31的写入不会触发这一点,这很奇怪.
一些未来的CPU可能会将物理寄存器文件中的条目配对以存储宽向量,即使它们通常不像AMD对256位向量那样解码以分离uop.
@Mysticial报告了使用YMM与ZMM但其他相同代码的长FP依赖链的代码意外减速,但后来的实验不同意当高256位为脏时SKX使用2x 256位寄存器文件条目作为ZMM寄存器的结论.
| 归档时间: |
|
| 查看次数: |
413 次 |
| 最近记录: |