AVX2 编译的程序仍然可以使用支持 AVX-512 的 CPU 的 32 个寄存器吗?

2023-12-10

假设以 AVX2 为目标的编译和 C++ 内在函数,如果我编写一个 nbody 算法,每个 body-body 计算使用 17 个寄存器,第 17 个寄存器可以间接(寄存器重命名硬件)或直接(Visual Studio 编译器、gcc 编译器)映射到 AVX 上-512 寄存器以切断内存依赖性?例如,skylake 架构有 1 或 2 个 AVX-512 fma 单元。这个数字是否也会改变可用寄存器总数? (具体来说,是 xeon silver 4114 cpu)

如果这有效,它是如何工作的?当所有指令均为 AVX2 或更少时,第一个硬件线程使用每个 ZMM 向量的前半部分,第二个硬件线程使用每个 ZMM 向量的后半部分?


Edit:如果目标机器上有在线编译(例如使用 OpenCL)怎么办?司机可以帮我做以上注册使用吗?


TL:DR: 编译-march=skylake-avx512让编译器使用 EVEX 前缀来访问 ymm16-31,这样它就可以(希望)为具有 17 的代码制作更好的 asm__m256价值观立刻“活”起来。

-march=skylake-avx512包括-mavx512vl


例如,skylake 架构有 1 或 2 个 AVX-512 fma 单元。这个数字是否也会改变可用寄存器总数?

不会,所有 Skylake CPU 中的物理寄存器文件大小相同,无论存在多少个 FMA 执行单元。这些东西是完全正交的。

64 位 AVX2 的架构 YMM 寄存器数量为 16 个,64 位 AVX512VL 的架构 YMM 寄存器数量为 32 个。在 32 位代码中,即使使用 AVX512,也始终只有 8 个可用向量寄存器。 (因此对于大多数高性能计算而言,32 位已经非常过时了。)

The longer EVEX encoding required for YMM16-31 with AVX512VL1 + AVX2, but instructions with all operands in the low 16 can use the shorter VEX prefix AVX/AVX2 form of the instruction. (There's no penalty for mixing VEX and EVEX encodings, so VEX is preferable for code-size. But if you avoid y/zmm0-y/zmm15, you don't need VZEROUPPER; legacy-SSE instructions can't touch xmm16-31 so there's no possible problem.)

同样,这一切与存在的 FMA 执行单元的数量无关。

脚注1: AVX512F仅包含大部分指令的ZMM版本;大多数 YMM 指令的 EVEX 编码需要 AVX512VL。唯一具有 AVX512F 但不具有 AVX512VL 的 CPU 是 Xeon Phi、KNL / KNM,现已停产;所有主流 CPU 均支持其支持的所有 AVX512 指令的 xmm/ymm 版本。

如果我编写一个 nbody 算法,每个 body-body 计算使用 17 个寄存器,第 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 各 1 位)来允许访问超出 VEX 前缀可编码范围的 32 个架构向量寄存器。 (仅在 64 位模式下;32 位模式仍然只有 8 个。在 32 位模式下,VEX 和 EVEX 前缀是现有指令的无效编码,翻转这些额外的寄存器编号位将使它们解码为valid这些旧指令的编码而不是作为前缀。)


寄存器重命名允许reuse相同架构寄存器的不同值,没有任何错误的依赖关系。即它避免 WAR 和 WAW 危险;它是使无序执行工作的“魔法”的一部分。在考虑 ILP 和乱序执行时,它有助于保持更多价值,但它doesn't帮助您在简单的程序执行顺序的任何时候在架构寄存器中获得更多值。

例如,下面的循环只需要 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

但是,由于从 ymm0 的第一次写入到迭代中的最后一次读取有 8 个周期的延迟链(Skylake addps / mulps 各为 4 个周期),在没有寄存器重命名的 CPU 上,这将成为瓶颈。下一次迭代无法写入 ymm0,直到vmovaps在本次迭代中读取了该值。

但在乱序 CPU 上,多个迭代会同时进行,每次写入 ymm0 都会被重命名以写入不同的物理寄存器。忽略前端瓶颈(假设我们已展开),CPU 可以使用大约 8 个物理寄存器,保持足够的迭代运行,以每个时钟 2 个 addps/mulps 微指令使 FMA 单元饱和。 (或者更多,因为它们实际上不能在退休之前被释放,而不仅仅是在最后一个微指令读取该值后立即释放)。

有限的物理寄存器文件大小可以是无序窗口大小的限制,而不是 ROB 或调度程序大小.

(我们考虑了一段时间,Skylake-AVX512 对 ZMM 寄存器使用 2 个 PRF 条目,基于这个结果,但后来更详细的实验表明,AVX512模式会启动更宽的PRF,或者说上通道来补充现有的PRF,因此AVX512模式下的SKX仍然具有与256位物理寄存器相同数量的512位物理寄存器。看@BeeOnRope 和 @Mysticial 之间的讨论。我认为某处有更好的实验+结果记录,但我在 ATM 机上找不到。)


有关的:为什么mulss在Haswell上只需要3个周期,与Agner的指令表不同? (使用多个累加器展开 FP 循环)(答案:不是;OP对寄存器重用感到困惑。我的答案详细解释了很多细节,并进行了一些有趣的多个向量累加器的性能实验。)

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

AVX2 编译的程序仍然可以使用支持 AVX-512 的 CPU 的 32 个寄存器吗? 的相关文章

  • 设置 IRQ 映射

    我正在遵循一些教程和参考文献来尝试设置我的内核 我在教程中遇到了一些不熟悉的代码 但根本没有解释它 这是我被告知映射的代码16 IRQs 0 15 到 ISR 地点32 47 void irq remap void outportb 0x2
  • Visual Studio 2012 本机 C++ DLL x86 编译

    我最近将我的工具集从 Win 7 x86 Visual Studio 2010 升级到 Win 8 x64 Visual Studio 2012 但是 现在我的本机 C dll 编译为 x64 而不是 x86 除了将代码移至新操作系统并将其
  • 是否可以在Linux上将C转换为asm而不链接libc?

    测试平台为Linux 32位 但也欢迎 Windows 32 位上的某些解决方案 这是一个c代码片段 int a 0 printf d n a 如果我使用 gcc 生成汇编代码 gcc S test c 然后我会得到 movl 0 28 e
  • 在 x86 汇编中将 64 位常量移至内存

    我正在使用 Intel x64 程序集 NASM 编译器 尝试将 0x4000000000000000 常量移至内存 该常量在 ieee 754 标准双精度中应等于 2 0 我正在使用的代码是 define two 0x4000000000
  • 为什么在展开的 ADD 循环内重新初始化寄存器会使其运行速度更快,即使循环内有更多指令?

    我有以下代码 include
  • 何时可以重用avx指令中的源寄存器

    在 avx 指令中用作源的寄存器何时可以在指令开始处理后重用 例如 我想使用vgatherdps该指令消耗两个 ymm 寄存器 其中之一是位移索引 我意识到vgatherdps由于数据的局部性较差 因此需要花费大量时间来收集 位移索引寄存器
  • 超标量和 VLIW

    我想问一些关于ILP的问题 超标量处理器是标量处理器和矢量处理器的混合体 那么我可以说矢量处理器的架构遵循超标量吗 同时处理多个指令不会使体系结构超标量 因为流水线 多处理器或多核体系结构也可以实现这一点 这意味着什么 我读过 超标量 CP
  • CISC 机器 - 它们不只是将复杂指令转换为 RISC 吗?

    也许我在架构上存在误解 但如果机器有 比如说 乘法指令 该指令是否未转换为更小的指令 或者过于复杂以至于最终与等效的 RISC 指令具有相同的速度 乘法是一个不好的例子 它在两种体系结构中都是一条指令 将上面的 乘法 替换为 CISC 中更
  • 标志寄存器中保留/未定义位的用途是什么?

    在 Z80 8080 8085 和 8086 处理器的标志寄存器中 被记录为 保留 或 未定义 的位 1 3 5 的用途是什么 这些位未使用 也就是说 没有指令明确地将它们设置为任何值 设计人员认为 5 6 个标志就足够了 他们只是将标志寄
  • _mm_max_ss 在 clang 和 gcc 之间有不同的行为

    我正在尝试使用 clang 和 gcc 交叉编译一个项目 但在使用时发现一些奇怪的差异 mm max ss e g m128 a mm set ss std numeric limits
  • 在 Intel x86 架构上使用非 AVX 指令移动 xmm 整数寄存器值

    我有以下问题 需要使用 AVX2 以外的任何工具来解决 我有 3 个值存储在 m128i 变量中 不需要第四个值 需要将这些值移动 4 3 5 我需要两个功能 一个用于按这些值进行右逻辑移位 另一个用于左逻辑移位 有谁知道使用 SSE AV
  • ARM Cortex-M3 启动代码

    我试图了解 STM32 微控制器的 Keil realview v4 附带的初始化代码是如何工作的 具体来说 我试图了解堆栈是如何初始化的 In the 文档 http infocenter arm com help index jsp t
  • 是否有适用于双打 (__m128d) 的 Move (_mm_move_ss) 和 Set (_mm_set_ss) 内在函数?

    多年来 我有几次看到 in 中的内在函数float参数被转换为 m128使用以下代码 m128 b mm move ss m mm set ss a 例如 void MyFunction float y m128 a mm move ss
  • 将 XMM 寄存器压入堆栈

    有没有办法将打包双字整数从 XMM 寄存器推送到堆栈 然后在需要时将其弹出 理想情况下 我正在寻找通用寄存器的 PUSH 或 POP 之类的东西 我已经检查了英特尔手册 但我要么错过了命令 要么没有 或者我是否必须将值解压到通用寄存器然后推
  • gcc 删除内联汇编代码

    看起来 gcc 4 6 2 删除了它认为函数中未使用的代码 test c int main void goto exit handler asm volatile jmp 0x0 exit return 0 拆解main 0x0804840
  • x86 asm 图形设置的分辨率高于 640x480?

    我刚刚开始使用汇编语言 感觉像学习新东西 并且遇到了一些问题 到目前为止 我一直在浏览的所有教程都没有回答 或者太旧而无法知道 1 我尝试了一些搜索 也许我只是不知道正确的关键字 但我找不到用于更改屏幕分辨率等的图形模式的更新列表 我发现的
  • 如何反汇编、修改然后重新组装 Linux 可执行文件?

    无论如何 这可以做到吗 我使用过 objdump 但它不会产生我所知道的任何汇编器都可以接受的汇编输出 我希望能够更改可执行文件中的指令 然后对其进行测试 我认为没有任何可靠的方法可以做到这一点 机器代码格式非常复杂 比汇编文件还要复杂 实
  • x86 程序集 Pushl/popl 不适用于“错误:后缀或操作数无效”

    我是汇编编程的新手 正在努力解决编程基础 http savannah nongnu org projects pgubook 在带有 GNU 汇编器 v2 20 1 的 Ubuntu x86 64 桌面上 我已经能够汇编 链接执行我的代码
  • 如何使 gcc 为 -fpatchable-function-entry 发出多字节 NOP?

    gcc确实有能力使用多字节用于对齐循环和函数的 NOP 然而当我尝试 fpatchable function entry option https gcc gnu org onlinedocs gcc Instrumentation Opt
  • 让 GCC 使用进位逻辑进行任意精度算术而不需要内联汇编?

    当使用任意精度算术 例如 512 位整数 时 有没有办法让 GCC 在不使用内联汇编的情况下使用 ADC 和类似指令 乍一看 GMP 的源代码表明他们只是为每个支持的平台提供了汇编实现 这是我编写的测试代码 它将命令行中的两个 128 位数

随机推荐

  • 如何将一个巨大的矩阵逐行写入文件(fortran 90)

    我想将一个包含大量数据的矩阵逐行写入文件中 例如 我有一个 100 100 的矩阵 我想在文件中以 100 100 的形式保存它 但是 它不起作用 以下是我的代码和一些描述 N和M是数百左右的整数 RECL 是预期长度我设置了文件 但在这里
  • 如何通过行列切换进行矩阵转换?

    我有一个由元素组成的方阵 1 或 0 第 i 行切换会切换所有第 i 行元素 1 变为 0 反之亦然 并且第 j 列切换切换所有 第 j 列元素 我有另一个方阵 大小相似 我想将初始矩阵更改为 使用最少切换次数的最终矩阵 例如 0 0 1
  • 使用清单的 DLL 重定向

    我需要可靠地重定向应用程序对特定 DLL 的查找 使用 app exe local 方法不起作用 因为如果应用程序具有清单 嵌入或单独的文件 则本地文件将被忽略 因此 我尝试通过在清单中将 DLL 定义为私有程序集来进行 DLL 重定向 我
  • 线性时间排序? [关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 给定 0 n 3 1 范围内的 n 个整数的输入集 提供线性时间排序算法 这是我周四测试的回顾 我不知道如何解决这个问题 也看看相关的排序 鸽巢排序 or 计数排序 也基数排序正如普
  • 从 VSTO PowerPoint 功能区调用 VBA AddIn 宏

    我在这个问题上被困了几个小时 我正在用 C 开发一个 PowerPoint 插件 我想使用另一个插件 PPAM 文件 中的宏 PPAM 文件已安装并启用 在应用程序参考中我发现我需要使用Application Run方法 但我无法让它工作
  • Selenium——如何等待页面完全加载[重复]

    这个问题在这里已经有答案了 我正在尝试使用 Java 和 Selenium WebDriver 自动化一些测试用例 我有以下场景 有一个名为 产品 的页面 当我点击 查看详细信息 链接时 在 产品 页面中 会出现一个包含商品详细信息的弹出窗
  • 当组合根位于客户端时如何在 WCF 中注入依赖项

    在开始之前 我必须说 我可能咬得太多 但我正处于绝望的学习狂潮中 我需要很多帮助 我正在编写一个练习 从两本书中获取样本 1 Net 中的依赖注入 作者 Mark Seemann2 Brian Egan 和 Steve Valenzuela
  • React-router transitionTo 不是一个函数

    import React from react import Router Link Navigation from react router export default class ResourceCard extends React
  • 子图之间的箭头

    我决定玩玩this示例代码一点 我能够弄清楚如何在两个子图之间绘制一条直线 即使该线位于其中一个子图的边界之外 import matplotlib pyplot as plt import matplotlib as mpl import
  • 在 Python 中通过管道传输到脚本时无法启动交互式程序

    我有一个 python 脚本需要调用定义的 EDITOR or VISUAL 当单独调用 Python 脚本时 我可以启动 EDITOR没有任何问题 但是当我将某些内容传输到 Python 脚本时 EDITOR无法启动 现在 我正在使用 n
  • 在expect中使用argc和argv解析命令行

    我有一个期望例程 它需要生成一个进程并将我传递给期望例程的命令行参数传递给生成的进程 我的期望例程有以下几行 spawn myProcess argv 当我调用我的期望例程时 我从命令行调用它 如下所示 expect myRoutine
  • 停止并重新启动 VGG-16 上的训练

    我正在使用预训练的 VGG 16 模型进行图像分类 我添加了自定义最后一层 因为我的分类类数量为 10 我正在对模型进行 200 轮训练 我的问题是 如果我随机停止 通过关闭 python 窗口 在某个时期的训练 有什么办法吗 假设时期没有
  • SSRS:我可以知道用户是否在多值参数中选择了“ALL”吗?

    客户希望我重复报告页眉中的参数值 但是 如果他们只是在多值参数上选择 全选 则他们希望列出文本 任意 例如 一个参数具有一组固定的 9 个值 我将文本框的表达式硬编码为 Room Size iif Parameters pRoomCap C
  • Python Numpy Loadtxt - 转换 unix 时间戳

    我有一个包含许多行数据的文本文件 每行中的第一条数据是一个 unix 时间戳 例如1436472000 我在用numpy loadtxt在转换器的参数中 我想指定它将时间戳转换为 numpy 理解的日期时间 我知道这需要在0 在大括号中 但
  • 将运算符作为参数传递给 C 中的函数

    我想将大于 gt 和小于 你可以用宏做一些可怕的事情 但一般来说 不 你不能这样做 您通常接受两个参数函数并调用它 并且该函数可以使用 gt or lt 酌情参见the sort docs举个例子 也就是说 它不是超级高效 通过指针调用函数
  • Spring-Jersey 应用程序的 JerseyTest 中的资源模型验证失败

    我有一个带注释的 Spring Jersey 应用程序 我正在尝试使用以下命令为我的控制器设置单元测试JerseyTest 我在运行测试时遇到以下错误 但我无法弄清楚 我错过了什么 SEVERE Following issues have
  • Android:图像保存到位置

    我正在努力显示一组图像 然后如果用户愿意 可以将图像保存到 SD 卡上 我需要帮助将它们保存到外部存储 有人可以帮我解决这个问题吗 网格视图 public void onCreate Bundle savedInstanceState su
  • 对 3 维数组中每行的深度值求和

    我需要计算每个第一级元素的深层元素的总和 3 级数组示例 1 gt A gt AA gt 3 AB gt 5 B gt BA gt 2 2 gt C gt CA gt 4 D gt DA gt 1 DB gt 2 3 gt E gt EA
  • 在 WCF 中获取“在线”消息大小

    当我对 WCF 进行 SOAP 或 REST 调用时 我希望任一端 客户端和服务器 上的通道堆栈记录接收到的数据的在线大小 所以我猜我需要向两侧的通道堆栈添加自定义行为 也就是说 在服务器端 我将记录接收到的 IP 标头通告的大小 累计 直
  • AVX2 编译的程序仍然可以使用支持 AVX-512 的 CPU 的 32 个寄存器吗?

    假设以 AVX2 为目标的编译和 C 内在函数 如果我编写一个 nbody 算法 每个 body body 计算使用 17 个寄存器 第 17 个寄存器可以间接 寄存器重命名硬件 或直接 Visual Studio 编译器 gcc 编译器