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



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

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

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

SSE/AVX不提供检测此情况的硬件支持,即使是像addss这样的标量指令也是如此。SSE是为SIMD设计的,每个XMM向量有4个浮点,据推测英特尔不想在MXCSR中提供4位的位图。尽管这是一个可能的设计选择。

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


使用AVX512,您可以正常地进行add/sub/mul/div/sqrt计算(使用默认舍入(,然后再次使用舍入模式覆盖将其截断为0。请使用vcmpps使结果相等。比较完全相等的元素通过默认舍入模式向0舍入(或两次都精确(。当然,你可以使用朝-Inf或朝+Inf作为覆盖来检测它,而不是朝0。

AVX512的EVEX前缀可以根据每条指令对舍入模式覆盖进行编码,而无需更改MXCSR。这使得可以有效地做到这一点,比更改MXCSR效率高得多。例如CCD_ 5。注意,AVX512嵌入式舍入(er(仅可用于512位向量;不幸的是,您无法将其与AVX512VL一起使用来对256位矢量进行舍入覆盖,以避免当前Skylake系列CPU上使用512位矢量的最大turbo和其他缺点。使用ER也适用于SAE(抑制所有异常(,这意味着该指令根本不必更新MXCSR。AVX-512指令编码-{er}含义。

在asm语法中,rz=向零取整。见表2-36。EVEX嵌入式广播/舍入/SAE和矢量指令上的矢量长度。

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

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

这总是需要两条额外的指令:重复操作和比较。Mysticial建议在mulps之后使用FMA,如果您直接使用符号位而不是与零进行比较,则可能会避免这种情况。例如vmovmskps来获得整数位图,或者vxorpsvandps来组合一些向量,其中您关心的"真值"是符号位。这可能是vblendvps(它也只查看符号位(的输入,或者是最终的vmovmskps的输入。


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

显然,一些英特尔CPU确实将MXCSR重命名;某些微体系结构上存在MXCSR重命名暂停周期的perf事件(不确定是哪个(:

由于MXCSR寄存器重命名发生得与以前的MXCSR重命名过于接近而暂停。

所以更改它不需要消耗调度器,但这并不好。根据这一措辞,在附近更改两次可能会很糟糕。IDK,如果可能只有有限数量的物理MXCSR条目可以重命名,或者有其他限制的原因。

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

相关内容

最新更新