不同的 mmx、sse 和 avx 版本是互补的还是彼此的超集?
Posted
技术标签:
【中文标题】不同的 mmx、sse 和 avx 版本是互补的还是彼此的超集?【英文标题】:Are different mmx, sse and avx versions complementary or supersets of each other? 【发布时间】:2015-07-18 11:50:23 【问题描述】:我想我应该熟悉 x86 SIMD 扩展。但在我还没开始之前,我就遇到了麻烦。我找不到关于其中哪些仍然相关的良好概述。
x86 架构几十年来积累了大量数学/多媒体扩展:
MMX 3D现在! 上海证券交易所 SSE2 SSE3 SSSE3 SSE4 AVX AVX2 AVX512 我是不是忘记了什么?新的是否是旧的超集,反之亦然?或者它们是互补的?
其中一些是否已弃用?其中哪些仍然相关?我听说过对“旧 SSE”的提及。
其中一些是互斥的吗? IE。它们共享相同的硬件部件吗?
在现代 Intel / AMD CPU 上,我应该一起使用哪个来最大限度地提高硬件利用率?为了争论起见,我们假设我可以找到这些指令的适当用途……如果没有别的,那就用 CPU 给我的房子供暖。
【问题讨论】:
突然想到:没有一个被弃用; SSE 是一个系列,AVX 也是;混合 SSE 和 AVX 不是一个好主意。我确信***或官方文档可以解决这些细节。 @Jeff 3DNow!已弃用 是的,你忘记了 SSE4a 和 XOP。 有人可能会争辩说,对齐的加载指令已被弃用。自从 Nehalem 以来,没有理由使用它们,至少在纸面上是这样。 【参考方案1】:我最近更新了 SSE、AVX 和 x86(以及 SSE2、avx2)的标签 wiki。他们涵盖了很多。 tl;dr 摘要:AVX 汇总了所有以前的 SSE 版本,并提供了这些指令的 3 操作数版本。还有大多数 FP (AVX) 和 int (AVX2) insns 的 256b 版本。
有关各种 SSE 版本的摘要,请参阅***或 knm241 的更详细答案。
我们并不认为 SSE 会过时。更像是,将 AVX 视为相同旧 SSE 指令的新版本和更好版本。它们仍以非 AVX 名称在参考手册中(例如,PSHUFB
,而不是 VPSHUFB
。)您可以混合使用 AVX 和 SSE 代码,只要在需要时使用 VZEROUPPER
以避免性能将 VEX 与非 VEX insns 混合(在 Intel 上)的问题。因此,在处理您必须调用可能运行非 VEX SSE 指令的库,或者您的代码使用 SSE FP 数学,但只有在 CPU 支持的情况下才能运行一些 AVX 代码的情况时,会有些烦恼。
如果 CPU 兼容性不是问题,那么向量指令的旧版 SSE 版本将真正过时,就像现在的 MMX 一样。如果将 VEX 编码的 128b 版本算作 AVX,而不是 SSE,那么 AVX/AVX2 至少在各方面都要好一些。有时您仍会使用 128b 寄存器,因为您的数据仅以那么大的块的形式出现,但更常见的是使用 256b 寄存器一次对两倍的数据执行相同的操作。
SSE/AVX/x87-FP/整数指令都使用相同的执行端口。通过混合它们,您无法并行完成更多工作。 (Haswell 除外,其中 4 个 ALU 端口之一只能处理非向量 insn,如 GP reg ops 和分支)。
【讨论】:
嗯,knm241 和 Peter Cordes,你们俩都有很好的答案,相得益彰。关心合并信息吗?谢谢你们! 我会将这个标记为正确,因为它更短,所以另一个答案在这个之后仍然可见。 我将在我的第二段中引用 knm 的答案。我想让我的答案尽可能简短,所以它是目标。每个 SSE 版本中的内容列表可在其他地方获得。也许没有像 knm241 的回答那样总结得那么好。我确实添加了一段关于如果 CPU 兼容性不是问题,我们真的永远不会在新代码中使用向量指令的非 VEX 编码。我认为 VEX 编码有时会长 1 个字节,但通常不会。唯一不这样做的原因是在调用 SSE 代码时避免vzeroupper
无法重新编译/重新组装。
谢谢,那段让弃用的问题更清楚了【参考方案2】:
它们是互补的。
每个新的指令集扩展都会添加新的指令,并最终添加一个新的编程模型(例如新的寄存器)。
没有被弃用,出于兼容性原因,几乎不可能执行弃用指令。但是,如果不是很广泛传播,一些可选扩展可能不存在或从较新的型号(如 AMD 的 FMA4)中删除。 虽然有些是退化的,但可以使用 FPU 和 MMX 完成的所有事情都可以使用 SSE+ 更有效地完成。
在您可以使用其中一种或另一种的意义上,它们并不是互斥的,毕竟它们是指令而不是操作模式(例如真实模式与保护模式)。 唯一可能的“冲突”是在 MMX 和 FPU 之间,因为它们共享同一组寄存器的下部,但具有不同的编程模型。 新的向量寄存器已经从 128 位增长到 256 位和 512 位,每次以前的寄存器都变成了新寄存器的低位。
您可以一起使用它们,它们提供特定的硬件支持来实现简单的操作。
它们就像乐高积木,你只受你的想象力(或设计师的想象力)的限制。
这里是该指令集扩展的简单列表。仅列出了部分功能,完整参考请参见第 9 章到第 14 章的Intel Manual Vol1。
另请参阅https://hjlebbink.github.io/x86doc/,了解英特尔第 2 卷(指令集参考)手册的目录,其中包含在该手册条目中添加说明的扩展列表。
MMX 介绍 8 个 64 位寄存器 (MM0-MM7) 和指令以处理八个有符号/无符号字节、四个有符号/无符号字、两个有符号/无符号双字。
3DNow! 向 MMX 添加对单精度浮点操作数的支持。支持的操作很少,例如加法、减法、乘法。
上交所 引入 8/16 个 128 位寄存器 (XMM0-XMM7/15) 和指令以使用四个单精度浮点操作数。也在 MMX 寄存器上添加整数操作。 (SSE 的 MMX 整数部分有时称为 MMXEXT,在一些没有 xmm 寄存器和 SSE 浮点部分的非 Intel CPU 上实现。)
SSE2 介绍使用 2 个双精度浮点操作数以及 128 位 xmm 寄存器中的压缩字节/字/双字/四字整数的指令。
SSE3
添加一些不同的指令(主要是浮点),包括一种在 Pentium 4 上更好的特殊类型的未对齐加载 (lddqu
)、同步指令、水平加/减。
SSSE3
同样是一组不同的指令,主要是整数。第一个从寄存器而不是硬编码 (pshufb
) 中获取其控制操作数的 shuffle。更多的水平处理、shuffle、打包/解包、mul+add on bytes,以及一些专门的整数 add/mul 东西。
SSE4(SSE4.1、SSE4.2) 添加大量指令:通过为所有整数数据类型(尤其是 32 位整数一直缺乏)提供 min 和 max 以及其他操作来填补很多空白,其中以前整数 min 仅适用于无符号字节和有符号 16 -少量。还有缩放、FP 舍入、混合、线性代数运算、文本处理、比较。也是读取视频内存或将其复制回主内存的非临时负载。 (以前只有 NT 商店可用。)
AESNI 添加对加速 AES 对称加密/解密的支持。
AVX 添加八个/十六个 256 位寄存器 (YMM0-YMM7/15)。 支持所有以前的浮点数据类型。三个操作数指令。
FMA Add Fused Multiply Add 和相关指令。
AVX2 添加对整数数据类型的支持。
AVX512F 添加八个/三十二个 512 位寄存器(ZMM0-ZMM7/31)和八个 64 位掩码寄存器(k0-k7)。将大多数先前的指令提升到 512 位宽。 AVX512 的可选部分添加了指数和倒数指令 (AVX512ER)、分散/聚集预取 (AVX512PF)、分散冲突检测 (AVX512CD)、压缩、扩展。
IMCI(英特尔至强融核) 为第一代英特尔至强融核(Knight's Corner)协处理器开发 AVX512。
【讨论】:
很好的解释。我还要提一下,与 MMX/FP 重叠类似,XMMi 实际上是 YMMi 的下部,而这反过来又是 ZMMi 的下部。 @hayesti,是的。我正在更新答案。 不确定说任何可以用 FPU 完成的事情都可以用 SSE 更有效地完成。尝试使用 SSE 进行 80 位浮点数... 嗯,knm241 和 Peter Cordes,你们俩都有很好的答案,相得益彰。关心合并信息吗?谢谢你们! 您忘记了 SSE4a 和 XOP。 XOP 尤其重要,因为它添加了英特尔仅通过 AVX512 获得的 64 位比较指令。它完成了标量指令除了adc
和mulx
之外的整数运算集。以上是关于不同的 mmx、sse 和 avx 版本是互补的还是彼此的超集?的主要内容,如果未能解决你的问题,请参考以下文章
使用 C/C++ 在同一个可执行文件中进行不同的优化(plain、SSE、AVX)