SIMD指令降低CPU频率

61
我阅读了这篇文章,它讨论了为什么AVX-512指令会导致核心或整个CPU运行变慢,因为它们使用了很多功率。
我认为Agner的博客也提到了类似的问题(但我找不到确切的帖子)。 我想知道Skylake支持的其他指令是否有类似的影响,以后可能会降低功率来最大化吞吐量? 所有具有v前缀的指令(如vmovapdvmulpdvaddpdvsubpdvfmadd213pd)都是吗?
我正在尝试编译一份在Xeon Skylake上运行时需要避免的C++应用程序指令列表。

2
Trevis Down(在OS上的昵称为Beeonrope)在这篇文章的评论中写到了这个问题,并在这里继续讨论。他发现每个级别(标量、AVX/AVX2、AVX-512)都有“廉价”(无FP,简单操作)指令和“重型”指令。即使稀疏使用,廉价指令也会将频率降低到下一个更高级别的频率(例如,廉价AVX-512指令使用AVX/AVX2级别)。重型指令必须每次使用超过1次... - Margaret Bloom
2
...两个周期,并根据它们的层次降低频率(例如,AVX-512重型指令将频率降至AV-512基础)。Travis还分享了他用于测试的代码此处。您可以通过一点耐心或按照他的经验法则找到每个指令的行为。最后请注意,如果向量与标量指令的比率足够低,以至于数据处理的宽度增加不能平衡频率下降,则频率缩放是一个问题。检查最终二进制文件以确定是否真正获得了任何收益。 - Margaret Bloom
1
@HCSF 你可以制作三个版本,一个没有AVX指令集,一个带有AVX/AVX2指令集,还有一个带有AVX-512指令集(如果适用),并对它们进行性能测试。然后选择最快的版本。 - Margaret Bloom
1
Peter提到了-mpreferred-vector-width=256选项。我不知道它是否会阻止gcc在直接内部使用之外_永远_生成AVX-512指令,但这是可能的。然而,我不知道有任何区分“重”和“轻”指令的选项。通常这不是一个问题,因为如果你关闭AVX-512并且没有一堆FP操作,你可能正在针对L0,而AVX-512 light仍然是L1。 - BeeOnRope
1
@HCSF libc中的重要例程通常会为不同的ISA编译多次,然后使用动态加载器的IFUNC功能在运行时选择适合当前CPU的版本。因此,您通常会获得针对您的CPU进行优化的版本(除非您的libc非常旧且您的CPU非常新)。 - BeeOnRope
显示剩余11条评论
2个回答

84
在英特尔芯片上,频率影响和具体的频率转换行为取决于操作的宽度和使用的具体指令。
就指令相关的频率限制而言,有三个频率级别 - 所谓的许可证 - 从最快到最慢分别是:L0、L1和L2。L0是你会在盒子上看到的“名义”速度:当芯片说“3.5 GHz turbo”时,他们指的是单核心的L0 turbo。L1是一个较低的速度,有时被称为AVX turbo或AVX2 turbo[5],最初与AVX和AVX2指令相关联[1]。L2是比L1更低的速度,有时被称为“AVX-512 turbo”。
每个许可证的确切速度也取决于活动核心的数量。要获取最新的表格,通常可以参考WikiChip。例如,Xeon Gold 5120的表格在这里

Xeon Gold 5120 Frequencies

普通、AVX2和AVX512行分别对应L0、L1和L2许可证。请注意,随着核心数量的增加,L1和L2许可证的相对减速通常会变得更糟:对于1或2个活动核心,L1和L2速度分别为L0的97%和91%,但对于13或14个核心,它们分别为85%和62%。这因芯片而异,但一般趋势通常是相同的。
在解决了这些初步问题之后,让我们来谈谈我认为你在问什么:“哪些指令会激活哪些许可证”?
下面是一个表格,显示了根据指令的宽度和其被归类为“轻量级”或“重量级”的情况下所暗示的许可证:
   Width    Light   Heavy  
 --------- ------- ------- 
  Scalar    L0      N/A
  128-bit   L0      L0     
  256-bit   L0      L1*    
  512-bit   L1      L2*

*soft transition (see below)

所以我们立即看到,所有标量(非SIMD)指令和所有128位宽指令2在L0许可证中始终以全速运行。
256位指令将根据它们是“轻”还是“重”而在L0或L1中运行,而512位指令将根据相同的基础在L1或L2中运行。
那么这个“轻”和“重”是什么意思呢?
轻 vs 重
最简单的方法是从解释重指令开始。
重指令是需要在FP/FMA单元上运行的所有SIMD指令。基本上,这包括大部分FP指令(通常以pspd结尾,如addpd),以及大部分以vpmulvpmad开头的整数乘法指令,因为SIMD整数乘法实际上是在SIMD单元上运行的,还有vplzcnt(q|d)也是在FMA单元上运行的。
鉴于此,轻指令就是其他所有指令。特别是除了乘法之外的整数算术指令、逻辑指令、洗牌/混合指令(包括FP)以及SIMD加载和存储指令都属于轻指令。

过渡

列中的L1和L2条目用星号标记,如L1*。这是因为这些指令在发生时会引起过渡。另一个L1条目(针对512位轻指令)会引起硬过渡。在这里,我们将讨论这两种过渡类型。

硬过渡

一旦执行具有给定许可证的任何指令,就会立即发生硬过渡4。CPU停止运行,经过一些停机周期后进入新模式。

软过渡

与硬过渡不同,软过渡不会立即发生在任何指令执行时。相反,指令最初以降低的吞吐量执行(最慢为正常速度的1/4),而不改变频率。如果CPU决定每单位时间内正在执行足够多的重型指令,并且达到了特定的阈值,则会发生向更高编号的许可证的过渡。

也就是说,CPU明白,如果只有少量的重型指令到达,或者即使有很多指令到达但在考虑其他非重型指令时它们并不密集,那么减少频率可能是不值得的。

指导方针

根据上述情况,我们可以制定一些合理的指导方针。您永远不必担心128位指令,因为它们从不引起与许可证相关的3降频。

此外,你也不必担心256位宽指令会导致降频。如果你没有使用大量的向量化浮点数运算,那么你很可能也不会使用重型指令,所以这对你来说是适用的。实际上,编译器在你使用适当的-march选项时已经广泛地插入了256位指令,特别是用于数据移动和自动向量化循环。
然而,使用重型AVX/AVX2指令和轻型AVX-512指令就比较棘手了,因为你将会受到L1许可证的限制。如果你的进程只有一小部分(比如10%)能够受益,那么减慢应用程序的其余部分可能并不值得。与L1相关的惩罚通常是适度的,但请查看你的芯片的详细信息。
使用重型AVX-512指令更加棘手,因为大多数芯片上的L2许可证会带来严重的频率惩罚。另一方面,需要注意的是,只有浮点数和整数乘法指令属于“重型”类别,因此从实际角度来看,大量使用512位宽整数只会产生L1许可证的开销。

1虽然我们将会看到,这有点不准确,因为AVX-512指令可以将速度设置为此许可证,而一些AVX/2指令则不能。

2128位宽意味着使用xmm寄存器,无论它们是在哪个指令集中引入的 - 主流的AVX-512包含了大多数/全部新指令的128位变体。

3请注意“与许可证相关”的词句 - 您当然可能遭受其他导致降频的原因,例如热量、功率或电流限制,而128位指令可能会触发这种情况,但我认为在桌面或服务器系统上是相当不太可能的(低功耗、小尺寸设备另当别论)。

4显然,我们只谈论从一个更高级别许可证转换到另一个更高级别许可证的情况,例如当执行硬过渡L1指令时从L0转换到L1。如果您已经处于L1或L2状态,则不会发生任何转换 - 如果您已经处于相同级别,并且您不基于任何特定指令而转换到较低编号的级别,而是在一定时间内运行而没有任何较高编号级别的指令。

5个中,AVX2 turbo更常见,这一点我从来没有真正理解,因为与AVX相比,256位指令与AVX2同样相关,并且大多数实际触发AVX turbo(L1许可证)的重型指令实际上是AVX中的FP指令,而不是AVX2。唯一的例外是AVX2整数乘法。

评论不适合进行长时间的讨论;此对话已被移至聊天室 - Samuel Liew
1
@Zboson - 我认为它最初出现在Haswell服务器芯片中,即Haswell-EP或其他名称。AVX2 turbo speed这个名字对我来说从来没有太多意义:它主要影响AVX集合中的FP指令,而不是AVX2,后者主要是整数(整数乘法是一个例外)。英特尔自己在早期文档中使用AVX而不是AVX2。人们似乎喜欢称其为AVX2,也许是因为它是在AVX2成为新ISA的Haswell中推出的? - BeeOnRope
1
@BeeOnRope可能会为Saphire Rapids进行更改。似乎不再有任何许可证转换事件 - Noah
@user997112 我看不出来(旧链接已失效,文件已移动),但在他们的 GitHub 页面上仍然没有看到任何有关 SPR 许可转换事件的信息。我手头没有 SPR 机器,所以无法进行测试。 - Noah
@user997112 另外顺便提一下,我知道我们计划在GLIBC中默认启用avx512,因为频率限制不是一个问题,尽管这仅适用于"轻量级"指令。 - Noah
显示剩余10条评论

17

重要的不是指令助记符,而是512位向量宽度

您可以使用AVX-512VL指令的256位版本,例如vpternlogd ymm0,ymm1,ymm2,而不会导致AVX-512 turbo惩罚。

相关:动态确定恶意AVX-512指令执行位置是关于glibc初始化代码或其他东西中一个AVX-512指令留下了脏的上部ZMM导致剩余进程生命周期内最大turbo受限的情况。(或者直到vzeroupper)

虽然256位FP数学指令的轻/重使用还可能产生其他turbo影响,其中一些是由于热量原因。但通常在现代CPU上使用256位是值得的。

无论如何,这就是为什么gcc -march=skylake-avx512默认使用-mprefer-vector-width=256。对于任何给定的工作负载,值得尝试-mprefer-vector-width=512,也许是128,这取决于工作负载中有多少可以自动向量化。

告诉GCC调整您的CPU(例如-march=native),它将会做出明智的选择。虽然在桌面Skylake-X上,turbo惩罚比Xeon要小。如果您的代码确实从512位向量化中获益,则支付这个惩罚是值得的。

(还要注意 Skylake 系列 CPU 进入 512 位矢量模式的另一个主要影响:端口 1 上的矢量 ALU 将关闭,因此只有像popcntadd之类的标量指令可以使用端口 1。 因此,vpandvpaddb等吞吐量从每个时钟周期的 3 个降至 2 个。如果您使用带有两个 512 位 FMA 单元的 SKX,则额外的一个单元将在端口 5 上启动,因此 FMA 将与洗牌竞争。)

1
当我使用-march=skylake-avx512 -mprefer-vector-width=128编译时,我实际上看到了你刚才提到的-- vmovdqu64(%rdx),%xmm0vmovdqu64 0x10(%rsi),%xmm6等等。 看起来GCC 8.2做得不对(或者不是你期望的)? - HCSF
您的回答是否意味着仅使用 xmm 运行 AVX2 指令不会像使用 ymm 操作数指令一样产生任何惩罚? - xiver77
@PeterCordes(或Travis),我有一个与SO上无法发布的相关问题。你知道有关Sapphire Rapids架构的文档吗?通常的Intel文档和Agner Fog似乎都集中在Alderlake上。谷歌搜索只返回相同的销售PPT幻灯片。我对核心之间的通信和处理器间通信很感兴趣。我还想了解具体的内容- L1/2/3/local/remote/TLB延迟、执行端口等。 - undefined
1
@user997112:我还没有研究过自冰湖以来的互连变化,不过https://chipsandcheese.com/2023/03/12/a-peek-at-sapphire-rapids/在三月份进行了一些缓存和内存延迟测试。核心和L1缓存应该与奥德湖P核心相同(某些型号除外,可能有第二个512位FMA单元),所以https://uops.info/和Agner Fog的资料应该适用于执行端口。英特尔的优化指南可能会有一些相关内容。 - undefined
1
@user997112:我对那个微基准测试结果持怀疑态度。https://chipsandcheese.com/2023/11/07/core-to-core-latency-data-on-large-systems/ 报告了同一插槽内核对内核的最坏情况延迟为81纳秒,而跨插槽的最坏情况延迟似乎为155纳秒(平均值为59和138纳秒)。也许他们的测试方式不同,比如只激活这两个核心进行测试,而不是所有核心都积极地发送内核间流量,从而在网状互连和插槽之间的链路上产生更多争用?(真实工作负载不会一直进行内核间传输。) - undefined
显示剩余16条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接