如果您的程序+库不包含 SSE 指令,那么使用 VZEROUPPER 有用吗?

2024-04-14

我明白使用它很重要VZEROUPPER混合 SSE 和 AVX 代码时,但如果我只使用 AVX(和普通 x86-64 代码)而不使用任何旧版 SSE 指令怎么办?

如果我从未在代码中使用单个 SSE 指令,是否有任何性能原因导致我需要使用VZEROUPPER?

这是假设我没有调用任何外部库(可能正在使用 SSE)。


也可以看看首次使用 AVX 256 位向量会减慢 128 位向量和 AVX 标量运算 https://stackoverflow.com/questions/66874161/first-use-of-avx-256-bit-vectors-slows-down-128-bit-vector-and-avx-scalar-ops回复:如果任何上层脏了,则将 128 位 AVX 操作隐式扩展到 256 位。 (包括为了“轻型”与“重型”涡轮限制 https://stackoverflow.com/questions/56852812/simd-instructions-lowering-cpu-frequency)。这可能是使用的一个原因vzeroupper,特别是如果程序的某些区域使用 256 位向量(尤其是“轻型”指令,例如除乘法之外的整数内容),而其他区域则大量使用 128 位 FMA。没有vzeroupper,128 位 FP 数学指令可能会降低您的最大睿频,就像您一直在使用繁重的 256 位指令一样。 (如果你无论如何都这样做,也许没什么大不了的)。


你是对的,如果你的整个程序不使用any写入的非 VEX 指令xmm寄存器,你不需要vzeroupper以避免状态转换惩罚。

请注意,非 VEX 指令可能潜伏在 CRT 启动代码和/或动态链接器或其他非常不明显的地方。

也就是说,非 VEX 指令在运行时只能造成一次性惩罚。反之则不然:一条 VEX-256 指令通常可以生成非 VEX 指令(或仅使用该寄存器)程序的其余部分很慢 https://stackoverflow.com/questions/41303780/why-is-this-sse-code-6-times-slower-without-vzeroupper-on-skylake/41349852#41349852.


There's 混合 VEX 和 EVEX 时没有惩罚 https://stackoverflow.com/questions/46080327/what-is-the-penalty-of-mixing-evex-and-vex-encoded-scheme,所以不需要使用vzeroupper there.


在 Skylake-AVX512 上:vzeroupper or vzeroall是在弄脏 ZMM 寄存器后恢复 max-turbo 的唯一方法,假设您的程序仍在 xmm/ymm0..15 上使用任何 SSE*、AVX1 或 AVX2 指令。

也可以看看Skylake 是否需要 vzeroupper 来让 Turbo 时钟在仅读取 ZMM 寄存器、写入 k 掩码的 512 位指令后恢复? https://stackoverflow.com/questions/58568514/does-skylake-need-vzeroupper-for-turbo-clocks-to-recover-after-a-512-bit-instruc- 仅仅读取 zmm 不会导致这种情况。

发表者聊天中@BeeOnRope https://chat.stackoverflow.com/transcript/message/43768745#43768745:

AVX-512 指令对周围代码有一个新的、非常糟糕的影响:一旦执行 512 位指令(可能除了不写入 zmm 寄存器的指令),核心就会进入“上 256 脏状态” 。在此状态下,任何后续标量 FP/SSE/AVX 指令(任何使用 xmm 或 ymm 寄存器的指令)都将在内部扩展至 512 位。这意味着处理器将被锁定到不高于 AVX Turbo(所谓的“L1 许可证”),直到发布 vzeroupper 或 vzeroall 为止。

与早期 AVX 和旧版非 VEX SSE(仍然存在于 Skylake Xeon 上)的“脏上 128”问题不同,这会由于频率较低而减慢所有代码的速度,但不会出现“合并 uops”或错误依赖关系或类似的事情:只是较小的操作被有效地视为 512 位宽,以实现零扩展行为。

关于“写下半部分......” -不,它是一个全局状态,并且只有 vzero让你摆脱困境*。即使您弄脏了 zmm 寄存器但对 ymm 和 xmm 使用了不同的寄存器,也会发生这种情况。即使唯一的脏指令是像这样的归零惯用法,也会发生这种情况vpxord zmm0, zmm0, zmm0. 但写入 zmm16-31 时不会发生这种情况.

他的描述actually将所有向量运算扩展到 512 位并不完全正确,因为他后来证实这不会降低 128 和 256 位指令的吞吐量。但我们知道,当 512 位微指令运行时,端口 1 上的矢量 ALU 会关闭。 (因此,通常可通过端口 0 和 1 访问的 256 位 FMA 单元可以组合成一个 512 位单元,用于所有 FP 数学、整数乘法以及可能的其他一些内容。某些 SKX Xeon 在端口上有第二个 512 位 FMA 单元5、有些则不然。)


仅使用 AVX1 / AVX2 后的最大涡轮增压(包括像 Haswell 这样的早期 CPU):如果一段时间没有使用执行单元的上半部分,则机会性地关闭它们(有时允许更高的 Turbo 时钟速度)取决于最近是否使用过 YMM 指令,而不是取决于是否使用过 YMM 指令。上半部分是否脏。所以据我所知,vzeroupper does not对于 256 位最大睿频较低的 CPU,在使用 AVX1 / AVX2 后帮助 CPU 更快地取消时钟速度。

这与英特尔的 Skylake-AVX512 (SKX / Skylake-SP) 不同,其中 AVX512 有点“固定”。


VZEROUPPER可能会进行上下文切换slightly cheaper

因为CPU仍然知道ymm-upper状态是干净的还是脏的。

如果干净的话我觉得xsaveopt https://github.com/HJLebbink/asm-dude/wiki/XSAVEOPT or xsavec可以更紧凑地写出 FPU 状态,而无需存储全零的上半部分(只需设置一点表明它们是干净的)。注意在 SSE/AVX 的状态转换图中 https://stackoverflow.com/questions/41303780/why-is-this-sse-code-6-times-slower-without-vzeroupper-on-skylake/41349852#41349852 that xsave / xrstor是图片的一部分。

一个额外的vzeroupper仅当您的代码不使用任何 256b 指令时才值得考虑long在此之后的时间,因为理想情况下,在下次使用 256 位向量之前,您不会进行任何上下文切换/CPU 迁移。

这在 AVX512 CPU 上可能不太适用:vzeroupper / vzeroall https://www.felixcloutier.com/x86/vzeroall#vzeroall--vex-256-encoded-version-不要碰ZMM16..31,只碰ZMM0..15。所以之后你仍然可以有很多脏状态vzeroall.


(理论上合理):脏的上半部分可能会占用物理寄存器(尽管 IDK 没有任何证据证明这在任何真实的 CPU 上都是正确的)。如果是这样,它将限制 CPU 寻找指令级并行性的无序窗口大小。 (ROB 大小是另一个主要限制因素,但 PRF 大小可能是瓶颈 http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/.)

这在 Zen2 之前的 AMD CPU 上可能是正确的,其中 256b 操作被分成两个 128b 操作。 YMM 寄存器在内部作为两个 128 位寄存器进行处理,例如vmovaps ymm0, ymm1以零延迟重命名低 128,但上半部分需要一个微指令。 (看阿格纳·福格的微建筑 pdf http://agner.org/optimize/)。未知是否vzeroupper不过,实际上可以放弃上半部分的重命名。 AMD Zen 上的清零习惯(与 SnB 系列不同)仍然需要后端 uop 来写入寄存器值,即使对于 128b 低半部分也是如此;只有 mov-elimination 可以避免后端 uop。因此可能不存在可以重命名上层的物理零寄存器。

实验中ROB尺寸/PRF尺寸博客文章 http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/不过,表明 Sandybridge 中的 FP 物理寄存器文件条目是 256 位。vzeroupper不应该在带有 AVX/AVX2 的主流 Intel CPU 上释放更多寄存器。 Haswell 式的转换惩罚足够慢,以至于它可能会耗尽 ROB 来保存或恢复上部到未重命名的单独存储,而不是使用有价值的 PRF 条目。

Silvermont 不支持 AVX。它使用单独的退休登记档案 https://www.realworldtech.com/silvermont/4/对于架构状态,因此无序 PRF 仅保存推测的执行结果。因此,即使它确实支持 128 位半部的 AVX,上半部脏的陈旧 YMM 寄存器也可能不会占用重命名寄存器文件中的额外空间。

KNL(Knight's Landing / Xeon Phi)是专门为运行 AVX512 而设计的,因此推测其 FP 寄存器文件具有 512 位条目。它基于 Silvermont,但核心的 SIMD 部分不同(例如,根据 Agner Fog 的说法,它可以重新排序 FP/向量指令,而 Silvermont 只能推测性地执行它们,但不能在 FP/向量管道内重新排序)。尽管如此,KNL 也可能使用单独的退休寄存器文件,因此即使 ZMM 能够分割 512 位条目来存储两个 256 位向量,脏 ZMM 上层也不会消耗额外的空间。这不太可能,因为 KNL 上仅 AVX1/AVX2 的较大乱序窗口不值得花费晶体管。

vzeroupper在 KNL 上比主流 Intel CPU 慢得多(64 位模式下每 36 个周期一个),所以你可能不想使用,尤其是为了微小的上下文切换优势。


在 Skylake-AVX512 上,证据支持矢量物理寄存器文件为 512 位宽的结论。

某些未来的 CPU 可能会将物理寄存器文件中的条目配对来存储宽向量,即使它们通常不会像 AMD 对 256 位向量那样解码为单独的微指令。

@神秘报道 https://stackoverflow.com/questions/48892733/can-avx2-compiled-program-still-use-32-registers-of-an-avx-512-capable-cpu#comment84791900_48892842使用 YMM 与 ZMM 的长 FP 依赖链的代码会意外变慢,但其他方面的代码相同,但后来的实验不同意以下结论:当高 256 位脏时,SKX 对 ZMM 寄存器使用 2x 256 位寄存器文件条目。


Ice Lake/Sa​​pphire Rapids 上的 AVX-512 和物理寄存器

https://chipsandcheese.com/2023/01/15/golden-coves-vector-register-file-checking-with-official-spr-data/ https://chipsandcheese.com/2023/01/15/golden-coves-vector-register-file-checking-with-official-spr-data/

[...]
虽然在服务器 Ice Lake 上进行的测试表明英特尔的机制远没有那么复杂。相反,核心只是记住上一组 ZMM 寄存器是否正在使用。如果您使用 AVX-512 引入的任何额外寄存器(即 ZMM16 到 31),Ice Lake 会保留另外 16 个寄存器来保存已知良好状态。无论你触摸其中一个还是全部,都没有关系。 Golden Cove 是 Ice Lake 的继承者,可以使用类似的机制。

... 因此,Zen 4 没有采用与 Ice Lake 相同的寄存器保存优化。

但不幸的是,我不认为vzeroupper / vzeroall可以帮忙解决这个问题;它不会影响 ZMM16..31,因此无法将它们恢复到“干净”状态并释放那些额外的 16 个物理寄存器以用于乱序执行。

如果我理解正确的话,手动将它们异或归零will阻止他们使用物理寄存器(vpxord xmm16, xmm16, xmm16通过xmm31);要么有一个额外的位来指示全零,要么有一个物理零寄存器,重命名器可以将它们指向。但可能仍然有 16 个额外的 PRF 条目保留用于退休状态,即使实际的 RAT 条目没有指向它们。

随着他们归零,xsave/xrstor上下文切换时可能会回到 zmm16-31-unused 状态。 CPU 大概必须能够以某种方式返回到该状态,而不是冷启动或进入深度睡眠状态。

该文章还有一些其他有趣的发现,例如 320 个向量 PRF 条目中只有 220 个能够保存 512 位结果。因此,只要足够,就使用 256 位指令(例如,从缩小到 256 位开始进行水平缩减)可以帮助乱序执行器看得更远。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如果您的程序+库不包含 SSE 指令,那么使用 VZEROUPPER 有用吗? 的相关文章

  • 在汇编中使用 printf 会导致管道传输时输出为空,但可以在终端上使用

    无输出 https stackoverflow com questions 54507957 printf call from assembly do not print to stdout即使在终端上 当输出不包含换行符时也有相同的原因
  • 双线性序列给出奇数结果

    我试图让我的表现技能 不存在 达到标准 但在将公式写入代码时遇到了问题 这是我试图将其引用为 转换 为代码的公式 考虑一个序列 u 其中 u 定义如下 号码u 0 1是第一个u 对于每个x in u then y 2 x 1 and z 3
  • 磁盘寻道时间测量方法

    我编写了一个脚本来测量 HDD 上的寻道时间 并且其完成方式的微小变化会导致显着不同的时间 第一个周期在磁盘开头的区域内进行跳转 第二个周期选择磁盘上执行查找的随机区域 相同大小 这种方法显然不同 但我不明白为什么它会改变结果 请注意 对于
  • 在汇编中,指令指定数据类型吗?

    我是汇编语言编程 x86 的初学者 以下说法是否正确 在汇编中 BYTE WORD DWORD 等数据类型分别表示 8 位 16 位和 32 位模式 而不仅仅是整数 它们本身没有意义 它们只是位模式 使用它们的指令赋予了它们意义 汇编 代码
  • 比较运算符性能 <= 与 !=

    让我们首先声明代码可读性胜过微优化 我们应该将其留给编译器 这只是一个奇怪的案例 具体细节似乎与一般建议相比很有趣 因此 我在搞素数生成器函数 并提出了一种奇怪的行为 其中 人们建议效率最高 实际上效率最低 而 C private stat
  • 在 nHibernate 关系中使用实体的 Lite 版本?

    在某些情况下 出于性能原因 创建一个实体的轻量级版本 指向同一个表 但映射的列较少 这是一个好主意吗 例如 如果我有一个包含 50 列的联系人表 并且在一些相关实体中 我可能对 FirstName 和 LastName 属性感兴趣 那么创建
  • 用于选择特定 div 中具有特定类的锚元素的 jQuery 选择器是什么

    我有一些这样的代码 我想选择每个 a 带有类的标签status在 div 中foo div a class status a div 你可以这样做 foo find status a
  • Draggable JS Bootstrap 模式 - 性能问题

    对于工作中的项目 我们在 JavaScript 中使用 Bootstrap Modal 窗口 我们想让一些窗口可移动 但我们遇到了 JQuery 的性能问题 myModal draggable handle modal header Exa
  • 就分页分段内存而言的程序寿命

    我对 x86 Linux 机器中的分段和分页过程有一个令人困惑的概念 如果有人能澄清从开始到结束所涉及的所有步骤 我们将很高兴 x86 使用分页分段内存技术进行内存管理 任何人都可以解释一下从可执行的 elf 格式文件从硬盘加载到主内存到它
  • 海量记录的bulk_create最佳实践

    I use bulk create将 1 mio 记录插入到新表中 需要 80 秒 Django 只使用一个 CPU 核心 大约 25 CPU 但没有一个核心达到 100 我相信有改进的潜力 这是代码 class Stock models
  • 将 AT&T 语法转换为 INTEL 语法

    我发现这个 GAS 文件包含一些可以从 CD 启动的引导加载程序代码 我想研究它并尝试制作我自己的一个 但唯一的问题是它采用 AT T 语法而不是 Intel 语法 我对 AT T 语法一无所知 我尝试过使用 Intel2gas 转换器 但
  • JSON.stringify 对于大型对象来说非常慢

    我在 javascript 中有一个非常大的对象 大约 10MB 当我对其进行字符串化时 需要很长时间 因此我将其发送到后端并将其解析为一个对象 实际上是带有数组的嵌套对象 这也需要很长时间 但这不是我们在这个问题中的问题 问题 我怎样才能
  • 汇编PC相对寻址模式

    我正在研究数据路径 并一直在尝试理解分支指令 这就是我的理解 在 MIPS 中 每条指令都是 32 位 这是 4 个字节 所以下一条指令将是四个字节之外 举个例子 我说PC地址是128 我的第一个问题是理解这个128意味着什么 我目前的信念
  • SSE:如何将 _m128i._i32[4] 减少到 _m128i._i8

    我对 SSE 编码非常陌生 我想将 int32 类型的 m128i 4 的结果存储到 int8 类型的 m128i 中 m128i j i32 k 的值均在 127 和 127 之间 我认为伪代码如下 result i8 vec1 i8 0
  • Intel 上的 gcc 中的 _mm_pause 用法

    我参考过这个网页 https software intel com en us articles benefitting power and performance sleep loops https software intel com
  • 当跳转在 32 字节上不完全对齐时,使用 MITE(传统管道)代替 DSB(微指令缓存)

    这个问题曾经是这个 现已更新 问题 https stackoverflow com questions 59883527 unrolling 1 cycle loop reduces performance by 25 on skylake
  • 快速查询最新记录的方法?

    我有一张这样的表 USER PLAN START DATE END DATE 1 A 20110101 NULL 1 B 20100101 20101231 2 A 20100101 20100505 在某种程度上 如果END DATE i
  • 1.2.840.113556.1.4.1941 (LDAP_MATCHING_RULE_IN_CHAIN) 存在性能问题?

    LDAP 搜索有一些内置规则 其中之一是LDAP MATCHING RULE IN CHAIN From MSDN https msdn microsoft com en us library aa746475 v vs 85 aspx 1
  • Nasm 点状标签

    我对 TASM 很熟悉 但对 NASM 不太了解 我读过 NASM 允许使用本地标签 这些标签在名称前用点表示 例如 代码 loop some code jmp loop 定义一个名为 loop的局部标号 引用的地址在后面的jmp指令中使用
  • 使用8086汇编语言画圆[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我试图使用 8086 汇编器画一个圆 我尝试利用中点圆算法 https en wikipedia org wiki Midpoin

随机推荐

  • css位置固定根本不起作用

    我正在寻找一个页脚类型的东西布莱克霍利网站 http www blakehawley com它有一些不同的链接等 它应该是横幅样式 我的意思是它应该停留在底部并被修复 div 是 菜单 这是我的 HTML
  • 当 merge.ff = only 时如何挤压合并?

    首先 我有我的merge ff设置为only as in git config global merge ff only 我这样做是因为我不希望 git 在没有先与我检查的情况下进行非快进合并 这是一个很好的保障 确保我有机会做一些除了创建
  • ServiceStack AppHost 是单例吗?

    我一直在评估 ServiceStack 到目前为止 我已经被说服了 但我有一个要求 think将会破坏交易 我基本上需要多个 AppHost 派生的实例 第一个运行良好 但其余的则失败 因为 AppHostBase Instance 已被设
  • 执行 tail -F 直到匹配模式

    我想做一个tail F在文件上直到匹配模式 我找到了一种使用方法awk 但恕我直言 我的命令并不是很干净 问题是我need由于某些限制 只能用一行来完成 tail n 0 F tmp foo awk W interactive if 1 E
  • 使用支持库 v21 设置 SearchView Widget 的样式

    我正在尝试使用新的 AppCompat v21 设计 SearchView 小部件的样式 但我遇到了一些问题 无论我在 suggestionRowLayout 属性上设置什么布局 它都不会执行任何操作 SearchView 的建议下拉列表保
  • R中5个排名的频率统计

    假设我有 5 件商品A B C D E并让受访者对它们进行排名 数据看起来像这样 gt df rank1 rank2 rank3 rank4 rank5 1 A B C D E 2 A C B D E 3 C A B E D 4 B A C
  • 如何避免 jasmine 在不同环境下出现较长的相对路径(../../../)?

    我目前正在开发一个项目 我想在不同的环境中进行测试 包括 node js 和带有 karma selenium 的不同浏览器 以避免兼容性问题 我想我会在浏览器中使用browserify 但我还不熟悉它 我有一个嵌套的测试目录 如下所示 r
  • verilog 中的案例陈述

    我遇到了优先级编码器设计 并找到了一种使用 case 语句来实现它的新方法 唯一令人困惑的是 case语句是否优先考虑case 例子 case 1 b1 A 3 Y lt 4 b1000 A 2 Y lt 4 b0100 A 1 Y lt
  • toDataURL 不是函数

    我正在尝试为画布生成一个网址 以下是我遵循的步骤 var can document getElementsByTagName canvas var src can toDataURL image png 当我尝试在 firebug 上运行上
  • 导航架构:如何在不使用clearTask的情况下管理正确的导航,因为它已被弃用

    当使用导航架构时here https issuetracker google com issues 116831650 here https issuetracker google com issues 80338878不推荐使用clear
  • 蓝牙文件发送

    我是蓝牙开发的新手 我发现了 32netfeet 现在我可以搜索附近的蓝牙设备并连接到它们 但如何发送文件 例如 SendTest txt 我尝试使用 OBEX 的 buttonclick 事件 但我不明白这是我的示例代码 using In
  • powershell 中的 DLLImport 用于使用相对路径访问 C 风格 32 位 API

    我想用powershell中的相对路径导入dll 下面是我尝试导入 dll 的代码片段 dirpath split path MyInvocation MyCommand Definition testDllPath dirpath Tes
  • SQL Server Management Studio (SSMS):最近的文件 (MRU) 菜单过于缩写而无法使用

    我在查找要编辑的正确 SQL 文件时遇到问题最近的文件 有时称为 MRU 最新版本的 SSMS 中的列表 我使用的是 18 5 我的文件具有相似的名称或相同的名称 但位于不同的文件夹中 这在 SSMS 的早期版本 我认为是 18 之前的版本
  • JavaScript 正则表达式匹配平衡结构而不关心不平衡结构

    我正在开发一个基于 JavaScript 的项目 该项目涉及一个基本的 Bash 启发的脚本系统 并且我正在使用正则表达式将行分隔成 多种类型的 标记 一种这样的令牌类当然是递归的 构造 该结构可以任意嵌套 我正在尝试设计一个 JavaSc
  • tkinter.ttk.Treeview根节点图标/图像不出现

    Problem 我无法让图标图像出现在 tkinter ttk Treeview 中根节点旁边 下面是我使用的测试代码 它执行时没有错误 但图像没有出现在根节点的左侧 我尝试过使用图像文件的完整路径名 但这不起作用 另外 我尝试使用 PIL
  • HTML5 Canvas 动画偶尔出现抖动/犹豫/卡顿

    在 Firefox 11 中 我在使用 HTML5 画布和翻译的一些基本动画中偶尔遇到抖动 犹豫 口吃的情况 请看下面的例子 http jsfiddle net ACRdx http jsfiddle net ACRdx 上面示例中的配置似
  • PrimeFaces 文件上传

    我正在一个项目中使用 jsp Servlet 并且决定使用 PrimeFaces 迁移到 JSF 我在尝试使用 PrimeFaces 文件上传控件上传文件时遇到了问题 然后当我将其配置到 web xml 中时 它运行良好 问题就来了现在所有
  • 警告:函数作为 React 子项无效。 (反应原生)

    我收到错误 警告 函数作为 React 子项无效 我正在编写一个 React Native 应用程序 interface RegisterScreenProps navigation NavigationContainerRef const
  • jquery文本区域长度计数?

    我有一个文本区域字段 当用户在该字段中输入一些文本时 我需要提供有关字数的信息 该字段的长度应为 500 个字符 最初它必须显示 最少字符数 100 0 of 500 0 of 500 必须为红色 一旦用户输入了字符 也需要更新计数 一旦用
  • 如果您的程序+库不包含 SSE 指令,那么使用 VZEROUPPER 有用吗?

    我明白使用它很重要VZEROUPPER混合 SSE 和 AVX 代码时 但如果我只使用 AVX 和普通 x86 64 代码 而不使用任何旧版 SSE 指令怎么办 如果我从未在代码中使用单个 SSE 指令 是否有任何性能原因导致我需要使用VZ