x64 SSE数据类型

rwa*_*ace 7 64-bit assembly sse

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

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

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

我错过了什么?

tc.*_*tc. 1

Intel \xc2\xae 64 和 IA-32 架构优化参考手册§5.1 提到了有关混合整数/FP“数据类型”的类似内容(但奇怪的是不是单打和双打):

\n\n
\n

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

\n\n

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

\n
\n\n

Intel \xc2\xae 64 和 IA-32 Architectures\nSoftware Developer\xe2\x80\x99s 手册同样令人困惑:

\n\n
\n

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

\n\n

...

\n\n

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

\n\n

...

\n\n

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

\n\n

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

\n\n

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

\n
\n\n

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

\n\n
    \n
  • AIUI、x86 内核由于寄存器短缺通常使用寄存器重命名。也许它们在内部对整数/单/双操作数使用不同的寄存器,因此它们可以位于更靠近各自向量单元的位置。
  • \n
  • FP 数似乎也有可能在内部使用不同的格式表示(例如,使用更大的指数来消除分母),并仅在必要时转换为规范位。
  • \n
  • CPU使用“转发”或“旁路”,以便执行单元不必等待数据写入寄存器即可供后续指令使用,通常可以节省一两个周期。在整数和 FP 单元之间可能不会发生这种情况。
  • \n
\n