SSE/AVX 是否提供确定结果是否四舍五入的方法?

sup*_*owl 4 x86 sse simd rounding avx

C1x87 FPU 状态字中该位的用途之一是显示是否对不精确的结果进行了四舍五入。

SSE/AVX 是否为标量操作提供任何此类指示?

我在MXCSR寄存器中没有看到类似的位。如果我需要这些信息,我是否必须使用 x87 指令?

Pet*_*des 5

SSE/AVX 不提供硬件支持来检测这一点,即使对于像addss. SSE 是为 SIMD 设计的,每个 XMM 向量有 4 个浮点数,大概英特尔不想在 MXCSR 中提供 4 位的位图。虽然这本来是一个可能的设计选择。

正如@Mysticial 在评论中指出的那样,可以使用额外的指令来计算它。


(未经测试的想法可能会做你想做的事情。我认为这甚至应该适用于次正规等;完全相等的比较与按位比较相同,除了 -0.0 == +0.0 或 NaN)

随着AVX512,你可以做你的加/减/ MUL / DIV /开方计算正常(默认四舍五入),然后与舍入模式覆盖再次截断向0 使用vcmpps上的结果平等。完全相等的元素通过默认舍入模式向 0 舍入(或两次都精确)。当然,您可以使用朝向 -Inf 或朝向 +Inf 作为覆盖来检测它而不是朝向 0。

AVX512 的 EVEX 前缀可以在每条指令的基础上编码舍入模式覆盖,而无需更改 MXCSR。这使得执行此操作成为可能,明显比更改 MXCSR 更有效。例如_mm512_add_round_ps (__m512 a, __m512 b, int);。请注意,AVX512 嵌入式舍入 ( er) 仅适用于 512 位向量;不幸的是,您不能将它与 AVX512VL 一起使用来对 256 位向量进行舍入覆盖,以避免在当前 Skylake 系列 CPU 上使用 512 位向量的当前 max-turbo 和其他缺点。使用 ER 也适用 SAE(抑制所有异常),这意味着指令根本不必更新 MXCSR。 AVX-512 指令编码 - {er} 含义

在 asm 语法中,rz= 向零舍入。见表2-36。EVEX Embedded Broadcast/Rounding/SAE 和 Vector Length on Vector Instructions in Intel's vol.2 x86 manual

    vaddpd     zmm2, zmm1, zmm0          ; no override, or {rne-sae} would be Nearest-Even

    vaddpd     zmm3, zmm1, zmm0, {rz-sae}  ; rounding = truncation toward Zero
    vcmpneqpd  k1, zmm2, zmm3              ; compare for not-equal
   ;;; k1 = bitmask
       ;;  0 means rounded toward 0 or exact
       ;;  1 means rounded away from 0
Run Code Online (Sandbox Code Playgroud)

如果您不需要主要结果是 512 位向量,您可以这样做并与 XMM 或 YMM 寄存器进行比较,但{rz-sae}操作必须是 ZMM。YMM 比较使您可以选择与另一个 YMM 寄存器 (AVX1) 进行比较,而不是与 AVX512 掩码寄存器进行比较。但是如果您使用的是 AVX512,掩码寄存器通常非常好。

这总是需要 2 个额外的指令:重复操作和比较。Mysticial 建议在之后使用 FMAmulps可能会避免这种情况,如果您只是直接使用符号位而不是与零进行比较。例如,vmovmskps得到一个整数位,或vxorps或者vandps一些载体里的“真值”你关心的是符号位结合。这可能是vblendvps(也只查看符号位)的输入,或者是最终的vmovmskps.


在没有 AVX512 的情况下更改舍入模式可能不是一场彻底的灾难,特别是如果您可以在更改为截断并重做之前使用默认设置执行一些向量。如果您有足够的寄存器可以在足够多的操作上分摊 MXCSR 更改,那么这可能使它比每个向量需要 3 个或更多指令的舍入方向检测序列更有效。

显然,某些 Intel CPU 确实重命名了 MXCSR;某些微架构上存在MXCSR 重命名停顿周期的性能事件(不确定是哪个):

由于 MXCSR 寄存器重命名与之前的 MXCSR 重命名太接近而导致停顿。

因此,更改它不必耗尽调度程序,但这并不是很好。根据那个措辞,在附近更改两次可能很糟糕。IDK,如果可能只有有限数量的物理 MXCSR 条目需要重命名,或者有其他一些原因导致该限制。

当然,在循环中,您不会存储、位翻转和重新加载 MXCSR 值;您在内存中有两个 MXCSR 值,并且只有ldmxcsr它们。