7

AMD64 架构程序员手册第 1 卷:应用程序编程第 226 页关于 SSE 指令说:

处理器在执行指令之前不会检查指令操作数的数据类型。它只在执行时检查它们。例如,如果处理器执行的算术指令采用双精度操作数,但 MOVx 指令提供了单精度操作数,则处理器将在执行算术运算之前首先将操作数从单精度转换为双精度,然后结果将是正确的。但是,所需的转换可能会导致性能下降。

我不明白这一点;我原以为 ymm 寄存器只包含 256 位,每条指令根据其预期的操作数进行解释,由您来确保存在正确的类型,在所描述的场景中,CPU 将全速运行并默默地给出错误的答案。

我错过了什么?

4

1 回答 1

1

英特尔® 64 和 IA-32 架构优化参考手册§5.1 对混合整数/FP“数据类型”说了类似的话(但奇怪的是不是单数和双数):

在编写适用于整数和浮点数据的 SIMD 代码时,请使用 SIMD 转换指令或加载/存储指令的子集,以确保 XMM 寄存器中的输入操作数包含正确定义以匹配指令的数据类型。

包含交叉类型使用的代码序列在不同的实现中产生相同的结果,但会导致显着的性能损失。强烈建议不要使用 SSE/SSE2/SSE3/SSSE3/SSE44.1 指令对 XMM 寄存器中类型不匹配的 SIMD 数据进行操作。

英特尔® 64 和 IA-32 架构软件开发人员手册同样令人困惑:

SSE 和 SSE2 扩展定义了打包和标量浮点数据类型以及 128 位 SIMD 整数数据类型的类型化操作,但 IA-32 处理器不会在架构级别强制执行这种类型化。他们只在微架构级别执行它。

...

Pentium 4 和 Intel Xeon 处理器执行这些指令时不会产生无效操作数异常 (#UD) 并将在寄存器 XMM0 中产生预期的结果(即每个寄存器的高 64 位和低 64 位将被视为双精度浮点值,处理器将相应地对它们进行操作)。

...

在此示例中: XORPS 或 PXOR 可用于代替 XORPD 并产生相同的正确结果。然而,由于操作数数据类型和指令数据类型之间的类型不匹配,由于指令在微体系结构级别的实现会导致延迟损失。

使用错误类型的移动指令也可能导致延迟损失。例如,MOVAPS 和 MOVAPD 都可用于将压缩的单精度操作数从内存移动到 XMM 寄存器。但是,如果使用 MOVAPD,则当正确键入的指令尝试使用寄存器中的数据时,将产生延迟损失。

请注意,将数据从 XMM 寄存器移动到内存时不会产生这些延迟损失。

真的不知道“他们只在微架构级别执行它”是什么意思,除了它表明不同的“数据类型”被 μarch 以不同的方式处理。我有几个猜测:

  • AIUI、x86 内核由于寄存器不足,通常使用寄存器重命名。也许它们在内部为整数/单/双操作数使用不同的寄存器,因此它们可以更靠近相应的向量单元。
  • FP 数字似乎也可能在内部使用不同的格式表示(例如,使用更大的指数来摆脱 denorms)并仅在必要时转换为规范位。
  • CPU 使用“转发”或“绕过”,因此执行单元不必等待数据写入寄存器,然后才能被后续指令使用,通常可以节省一两个周期。这可能不会发生在整数和 FP 单元之间。
于 2013-03-10T20:42:34.713 回答