首次使用 AVX 256 位向量会减慢 128 位向量和 AVX 标量运算

2023-11-30

最初,我试图重现 Agner Fog 的微架构指南部分“YMM 和 ZMM 向量指令的预热期”中描述的效果,其中写道:

处理器在不使用时关闭向量执行单元的上部部分,以节省电力。在大约 56,000 个时钟周期或 14 μs 的初始预热期间,具有 256 位向量的指令的吞吐量大约比正常情况慢 4.5 倍。

我得到了减速,尽管看起来更接近 2 倍而不是 4.5 倍。但我发现在我的 CPU(Intel i7-9750H Coffee Lake)上,速度下降不仅影响 256 位操作,还影响 128 位向量操作和标量浮点操作(甚至 N 个仅 GPR 的操作) XMM 触摸指令之后的指令)。

基准程序代码:

# Compile and run:
# clang++ ymm-throttle.S && ./a.out

.intel_syntax noprefix

.data
L_F0:
  .asciz "ref cycles = %u\n"

.p2align 5
L_C0:
  .long 1
  .long 2
  .long 3
  .long 4
  .long 1
  .long 2
  .long 3
  .long 4

.text

.set initial_scalar_warmup, 5*1000*1000
.set iteration_count, 30*1000
.set wait_count, 50*1000

.global _main
_main:
  # ---------- Initial warm-up
  # It seems that we enter _main (at least in MacOS 11.2.2) in a "ymm warmed-up" state.
  #
  # Initial warm-up loop below is long enough for the processor to switch back to
  # "ymm cold" state. It also may reduce dynamic-frequency scaling related measurements
  # deviations (hopefully CPU is in full boost by the time we finish initial warmup loop).

  vzeroupper

  push rbp
  mov ecx, initial_scalar_warmup

.p2align 4
_initial_loop:
  add eax, 1
  add edi, 1
  add edx, 1

  dec ecx
  jnz _initial_loop

  # --------- Measure XMM

  # TOUCH YMM.
  # Test to see effect of touching unrelated YMM register
  # on XMM performance.
  # If "vpxor ymm9" below is commented out, then the xmm_loop below
  # runs a lot faster (~2x faster).
  vpxor ymm9, ymm9, ymm9

  mov ecx, iteration_count
  rdtsc
  mov esi, eax

  vpxor xmm0, xmm0, xmm0
  vpxor xmm1, xmm1, xmm1
  vpxor xmm2, xmm2, xmm2
  vmovdqa xmm3, [rip + L_C0]

.p2align 5
_xmm_loop:
  # Here we only do XMM (128-bit) VEX-encoded op. But it is triggering execution throttling.
  vpaddd xmm0, xmm3, xmm3
  add edi, 1
  add eax, 1

  dec ecx
  jnz _xmm_loop

  lfence
  rdtsc
  sub eax, esi
  mov esi, eax  # ESI = ref cycles count

  # ------------- Print results

  lea rdi, [rip + L_F0]
  xor eax, eax
  call _printf

  vzeroupper
  xor eax, eax
  pop rbp
  ret​

Question:我的基准正确吗?对正在发生的事情的描述(如下)看起来合理吗?

CPU 处于 AVX 冷状态(约 675 µs 内未执行 256 位/512 位指令)遇到带有 YMM (ZMM) 目标寄存器的单个指令。 CPU 立即切换到某种“过渡到 AVX-warm”状态。 Agner 指南中提到,这大概需要大约 100-200 个周期。这个“过渡”期持续约 56'000 个周期。

在过渡期间,GPR 代码可以正常执行,但任何具有向量目标寄存器的指令(包括 128 位 XMM 或标量浮点指令,甚至包括vmovq xmm0, rax) 将限制应用于整个执行管道。这会影响紧随此类指令的 N 个周期的仅 GPR 代码(不确定有多少;可能相当于指令的十几个周期)。

也许限制会限制分派到执行单元的微操作数(无论这些微操作是什么;只要至少有一个带有向量目标寄存器的微操作)?


对我来说,这里的新内容是,我认为在过渡期间限制将仅适用于 256 位(和 512 位)指令,但似乎任何具有向量寄存器目标的指令都会受到影响(以及〜20- 60 的探地雷达 - 仅立即遵循说明;无法在我的系统上进行更精确的测量)。


相关:“仅电压转换”部分Travis Downs 博客上的一篇文章可能正在描述相同的效果。尽管作者在过渡期间测量了 YMM 向量的性能,但得出的结论是,并不是向量的上半部分被分割,而是在过渡期间遇到向量寄存器接触指令时对整个流水线进行了限制。 (编辑:博客文章没有在过渡期间测量 XMM 寄存器,而这正是本文所测量的)。


事实上,即使对于窄 SIMD 指令,您也会看到限制,这是我称之为行为的副作用隐式扩大.

基本上,在现代 Intel 上,如果高 128-255 位是脏的any注册范围内ymm0 to ymm15, anySIMD 指令在内部扩展至 256 位,因为高位需要清零,这需要为寄存器文件中的完整 256 位寄存器供电,并且可能还需要为 256 位 ALU 路径供电。因此,该指令对于 AVX 频率而言就像 256 位宽一样。

类似地,如果位 256 到 511 是脏的anyzmm寄存器在范围内zmm0 to zmm15,操作隐式扩展至 512 位。

出于轻指令与重指令的目的,加宽指令的类型与全宽指令的类型相同。也就是说,扩展至 512 位的 128 位 FMA 充当“重型 AVX-512”,即使仅出现 128 位 FMA。

这适用于使用 xmm/ymm 寄存器的所有指令,even标量 FP 运算。

请注意,这不仅仅适用于此节流周期:这意味着如果上层脏了,窄 SIMD 指令(或标量 FP)将导致转换到更保守的 DVFS 状态,就像全角指令一样。

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

首次使用 AVX 256 位向量会减慢 128 位向量和 AVX 标量运算 的相关文章

  • 我可以使用 AVX FMA 单元进行位精确的 52 位整数乘法吗?

    AXV2 doesn t have any integer multiplications with sources larger than 32 bit It does offer 32 x 32 gt 32 http www felix
  • 将 AT&T 语法转换为 INTEL 语法

    我发现这个 GAS 文件包含一些可以从 CD 启动的引导加载程序代码 我想研究它并尝试制作我自己的一个 但唯一的问题是它采用 AT T 语法而不是 Intel 语法 我对 AT T 语法一无所知 我尝试过使用 Intel2gas 转换器 但
  • 在汇编中初始化字符串数组

    我想创建一个数据数组 在初始化数据部分保存 5 个字符串 每个字符串正好有 4 个字符 每个字符串都有一些初始数据 例如第一个字符串的 abcd 第二个字符串的 efgh 等等 无效的 0任何字符串都不需要字符 如何用汇编语言初始化字符串数
  • x86-64 AMD 上 CALL 指令的操作数生成

    以下是示例程序 objdump 的输出 080483b4
  • 3 操作数 imul 指令在 ia-32 汇编中到底起什么作用?

    我正在阅读说明 imul 0xffffffd4 ebp ebx 4 eax 我对它到底在做什么感到困惑 我明白那个imul乘法 但我无法弄清楚语法 我知道并且更喜欢 Intel MASM 语法 所以我将使用它 请注意 操作数的顺序在 AT
  • 解释一下 AF 标志在 x86 指令中如何工作?

    我有一个小型 8086 模拟器 并且我已经有一个长期存在的错误了大约 2 年 因为 AF 在 sub 和 add 指令内无法正常运行 我当前计算其值的方法是 8 位数字和减法 uint8 t base subt base base 0xF
  • 问题与 Assembly x86-32 RET n 指令有关

    我知道 Ret n 的含义 但我无法弄清楚它在维护程序运行时堆栈方面的作用 我在那里有点困惑 ret 和栈有关系吗 ret n就好像ret add esp n 您可以将其用于 caller pops 调用约定 Plain ret就好像pop
  • 最佳 SSE 无符号 8 位比较

    我试图找到使用 SSE 最高 SSE 4 2 执行 8 位无符号比较的最佳方法 我正在处理的最常见情况是比较 gt 0U 例如 mm cmpgt epu8 v mm setzero si128 1 当然 这也可以被认为是对非零的简单测试 但
  • 如何将 4 位十六进制转换为 7 位 ASCII?

    作业是通过编写一个可以在 4 位十六进制和 7 位 ASCII 之间转换的子程序来学习汇编编程 起初我不知道 但经过一些研究后 我可以做出努力并绘制流程图并制作程序 但它并不完全正确 所以我请求您的指导来帮助我解决这个问题 实际的作业文本是
  • 原始 SQL 是用汇编语言还是 C 语言编写的? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何在ubuntu下使用nasm(汇编)从键盘读取单个字符输入?

    我在ubuntu下使用nasm 顺便说一句 我需要从用户的键盘获取单个输入字符 就像当程序询问您 y n 时 因此当按下按键并且不按 Enter 键时 我需要读取输入的字符 我用谷歌搜索了很多 但我发现的所有内容都与这条线有关 int 21
  • 深入了解事物如何打印到屏幕上(cout、printf)以及我在教科书上似乎找不到的真正复杂内容的起源

    我一直想知道这个问题 但至今还没有找到答案 每当我们使用 cout 或 printf 时 它们到底是如何打印在屏幕上的 文本是如何显示出来的 这里可能是一个相当模糊的问题 无论你给我什么 我都会工作 那么基本上这些功能是如何制作的 是汇编吗
  • 返回中断处理程序后程序计数器去了哪里?

    您好 我想知道当程序从中断服务程序返回时程序计数器去哪里 我知道当中断事件发生时PC被压入堆栈 但是下一个或同一个 刚刚执行的一个 被压入堆栈的地址是什么 当我们有 first instruction interrupt event her
  • 从 GP regs 加载 xmm

    假设您的价值观是rax and rdx你想加载到xmm登记 一种方法是 movq xmm0 rax pinsrq xmm0 rdx 1 虽然速度相当慢 有没有更好的办法 在最近的 Intel 或 AMD 上 你不会在延迟或 uop 计数方面
  • NASM 解析错误,需要指令

    我问过类似的问题here https stackoverflow com questions 11572021 problems with winasm and zen of assembly但我改变了汇编器 问题几乎完全改变了 所以为了避
  • ARM NEON 汇编器错误:“指令不能是有条件的”

    根据手臂信息中心 http infocenter arm com help index jsp topic com arm doc dui0489c CIHJCAAG htmlvadd 可以有条件地执行 但是当我尝试时 vaddeq f32
  • 用于 GNU C++ 的 SSE SSE2 和 SSE3 [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有一个简单的教程可以帮助我快速掌握 GNU C 中的 SSE SSE2 和 SSE3 如何在SSE中
  • 快速将每秒一个字节复制到新的内存区域

    我需要一种快速方法将每个第二个字节复制到新的 malloc 内存区域 我有一个包含 RGB 数据且每通道 16 位 48 位 的原始图像 并且想要创建每通道 8 位 24 位 的 RGB 图像 有没有比按字节复制更快的方法 我对SSE2了解
  • 为什么在Java中读取易失性和写入字段成员是不可扩展的?

    观察以下用 Java 编写的程序 完整的可运行版本如下 但程序的重要部分在下面的代码片段中 import java util ArrayList A not easy to explain benchmark class MultiVola
  • 动态生成向量常量的最佳指令序列是什么?

    最佳 意味着最少的指令 或最少的微指令 如果任何指令解码为多个微指令 机器代码大小 以字节为单位 是相等 insn 计数的决定因素 恒定生成本质上是新依赖链的开始 因此延迟的影响并不常见 在循环内生成常量也是不常见的 因此吞吐量和执行端口需

随机推荐

  • Swift 泛型和协议不适用于 UIKit [可能的错误]

    TL DR gt 滚动到底部 在尝试使用 Swift 面向协议编程来标记 Apple 时 我在尝试实现类之间的委托模式时偶然发现了以下问题 我将从这个例子开始 protocol PhotoHandlerParent class UIView
  • 获取图标128*128文件类型C#

    我需要获取文件类型 doc 或 txt 的图标 它的大小应为 128 128 并以良好的质量保存为 png 或 ico 文件 I used Icon ico Icon ExtractAssociatedIcon d 1 txt pictur
  • 如何从 python 集中删除自定义对象的实例?

    我正在用 python 进行一些基本的卡 牌组操作 下面你可以看到我的 Card 类和 Deck 类 假设我知道有些牌已经死了 并且想将它们从牌组中删除 import itertools SUIT LIST h s d c NUMERAL
  • 设置 Java 线程的优先级

    我有一个在几个线程中运行的程序 主线程与其他线程共享一个对象 在主线程中我调用了 synchronized obj do stuff 我怀疑主线程饥饿并且无法访问obj 如何提高主线程的优先级或者默认情况下它已经高于其他线程 Thread
  • Java:Swing:按下按钮后隐藏框架

    我在 java 框架中有一个按钮 按下该按钮时 它会从文本字段读取一个值 并使用该字符串作为尝试连接到串行设备的端口名称 如果连接成功 该方法返回 true 否则返回 false 如果它返回 true 我希望框架消失 然后将出现其他类中指定
  • 使用 OpenCSVSerde 时,hive 无法读取字符斜杠

    我在 hdfs 中的文件顶部定义了一个表 我正在使用 OpenCSV Serde 从文件中读取 但是 数据中的 斜杠字符在最终结果集中被省略 是否有我没有正确使用的 hive serde 属性 根据文档 escapeChar 应该可以解决这
  • 错误:被调用的对象不是函数或函数指针

    我有以下代码 z x y 1 printf d z z x y 2 x y printf d z z x y x y printf d z z 2 x y x y printf d z 我收到此错误消息 10 11 error called
  • Python 中的八皇后问题

    Python 中的 8 皇后问题 你好 我才开始教Python 所以有人可以解释下面写的代码 在互联网上找到的 吗 有些代码对我来说很复杂 请解释一下 谢谢 问题就在代码附近 BOARD SIZE 8 def under attack co
  • 笔画可以用作 SVG 中剪辑路径的一部分吗?

    我正在编写 MuPDF 的 SVG 输出 并且遇到了 SVG 功能的限制 我想我会在这里问 以防这是已知解决方法的已知问题 或者万一我做了一些愚蠢的事情 我有以下 SVG
  • 如何将行转换为基于重复列的数据?

    我正在尝试获取如下所示的数据集 并将记录转换为以下格式 生成的格式将有两列 一列用于旧列名称 一列用于值 如果有 10 000 行 那么新格式中应该有 10 000 组数据 我对所有不同的方法持开放态度 Excel 公式 sql mysql
  • 如何在 Python 中使用 OpenCV 拉直图像的旋转矩形区域?

    下面的图片会告诉你我想要什么 我有图像中矩形的信息 宽度 高度 中心点和旋转度 现在 我想编写一个脚本来剪切它们并将它们保存为图像 但也要拉直它们 例如 我想从图像内部显示的矩形转到外部显示的矩形 我正在使用 OpenCV Python P
  • 查找二叉树中最大独立集的大小 - 为什么错误的“解决方案”不起作用?

    这是一个类似问题的链接 有一个很好的答案 Java算法寻找二叉树中最大的独立节点集 我想出了一个不同的答案 但我的教授说这行不通 我想知道为什么 他不回复电子邮件 问题 给定一个包含 n 个整数的数组 A 其索引从 0 开始 即A 0 A
  • python 是否有类似于 __setattr__ 但针对 python 类的方法?

    现在 设置属性 仅适用于实例 课堂上有类似的方法吗 我问这个问题是因为当用户在类中定义属性时 我想按顺序收集已定义属性的列表 如下所示 class CfgObj object fields def setattr self name val
  • HandlerInterceptorAdapter 和 Zuul 过滤器

    可以添加一个HandlerInterceptorAdapter with Zuul配置 我需要拦截对特定资源的请求 但我想是因为我有Zuul过滤器配置 拦截器永远不会被调用 可以这样做吗 我也试图达到同样的目的 我们有一些 Spring M
  • 获取垃圾输出 Java [重复]

    这个问题在这里已经有答案了 我正在尝试用 Java 实现一个构造函数 我不知道我是否做错了什么 但我不断收到垃圾输出 这是我试图为其赋值的变量 private static Employee employee 这就是我尝试分配它的方式 em
  • AttributeError:'tuple'对象没有属性'encode' - MySQLdb Python

    我正在用 MySQL 编写 Python 代码 我的数据库架构如下 id name 以下是我的代码的一部分 cursor self conn cursor query SELECT name FROM TABLENAME WHERE id
  • 正则表达式 - 精确匹配一个标签

    我有一个正则表达式来从 HTML 字体标签中提取文本 font face font 在我有一些嵌套的字体标签之前 这一切都很好 而不是匹配 font face Fett font 字符串的结果 font face Fett font u U
  • 您可以导入 .so 文件吗?

    我有一个名为的 so 文件tissue classifier cpython 37m x86 64 linux gnu so来自我想要导入的外部库 以便我可以在我的本地类之一中扩展它 由于我正在扩展一个类 因此我需要使用以下命令将其作为扩展
  • 如何为 adobe air 应用程序设置图标

    我正在开发 Adob e Air 应用程序 我需要为应用程序设置一个图标 以便它显示在任务栏上 我将图标标签添加到描述符文件中 但它不起作用 我真的不知道为什么 有什么想法吗 有两件事可能会让你失望 1 图标块在自动生成的描述符文件中默认被
  • 首次使用 AVX 256 位向量会减慢 128 位向量和 AVX 标量运算

    最初 我试图重现 Agner Fog 的微架构指南部分 YMM 和 ZMM 向量指令的预热期 中描述的效果 其中写道 处理器在不使用时关闭向量执行单元的上部部分 以节省电力 在大约 56 000 个时钟周期或 14 s 的初始预热期间 具有