Function core::arch::x86::_mm_setcsr

1.27.0 · source ·
pub unsafe fn _mm_setcsr(val: u32)
Available on (x86 or x86-64) and target feature sse and x86 only.
Expand description

用 32 位无符号整数值设置 MXCSR 寄存器。

该寄存器控制 SIMD 指令如何处理浮点运算。修改该寄存器只会影响当前线程。

它包含几组标志:

  • 异常标志 报告自上次重置后发生了哪些异常。

  • 屏蔽标志 可用于屏蔽 (忽略) 的某些异常。默认情况下,这些标志都设置为 1,因此所有异常都被屏蔽。 屏蔽了异常后,处理器将简单地设置异常标志并继续操作。 如果未屏蔽该异常,则还会设置该标志,但是还会调用一个异常处理程序。

  • 舍入模式标志 控制浮点指令的舍入模式。

  • 非规范化为零模式 flags* 将所有将要归一化 (指数位全为零) 的数字转换为零。

异常标志

  • _MM_EXCEPT_INVALID: 执行了无效的操作 (例如,将无穷大除以无穷大)。

  • _MM_EXCEPT_DENORM: 试图对非规范化数字进行操作的操作。这主要会导致精度降低。

  • _MM_EXCEPT_DIV_ZERO: 发生被零除。

  • _MM_EXCEPT_OVERFLOW: 发生数值溢出异常,即结果太大无法表示 (例如,绝对值大于 2^128f32)。

  • _MM_EXCEPT_UNDERFLOW: 发生数字下溢异常,即结果太小而无法以规范化的方式表示 (例如,f32 绝对值小于 2 ^-126。)

  • _MM_EXCEPT_INEXACT: 发生不精确结果异常 (又名 精度异常)。这意味着由于舍入而损失了一些精度。 例如,分数 1/3 无法在 32 位或 64 位浮点数并对其进行计算将导致引发此异常。精度异常非常常见,因此通常会被屏蔽。

可以使用便捷函数 _MM_GET_EXCEPTION_STATE_MM_SET_EXCEPTION_STATE 读取和设置异常标志。 例如,要检查某个操作是否引起一些溢出:

_MM_SET_EXCEPTION_STATE(0); // 清除所有异常标志
                            // 执行计算
if _MM_GET_EXCEPTION_STATE() & _MM_EXCEPT_OVERFLOW != 0 {
    // 处理上溢
}
Run

掩蔽标志

每个异常标志都有一个屏蔽标志: _MM_MASK_INVALID_MM_MASK_DENORM_MM_MASK_DIV_ZERO_MM_MASK_OVERFLOW_MM_MASK_UNDERFLOW_MM_MASK_INEXACT

可以通过设置单个屏蔽位

_MM_SET_EXCEPTION_MASK(_MM_MASK_UNDERFLOW);
Run

但是,由于默认情况下所有掩码位都设置为 1,因此更常见的是要 禁用 某些位。例如,要掩盖下溢异常,请使用:

_mm_setcsr(_mm_getcsr() & !_MM_MASK_UNDERFLOW); // 暴露下溢
exception
Run

警告:未屏蔽的异常将导致调用异常处理程序。 标准处理程序将简单地终止该进程。 因此,在这种情况下,任何下溢异常都将使用诸如 signal: 8, SIGFPE: erroneous arithmetic operation 之类的内容终止当前进程。

舍入模式

使用两位描述舍入模式。可以使用便捷包装 _MM_GET_ROUNDING_MODE()_MM_SET_ROUNDING_MODE(mode) 进行读取和设置。

舍入模式为:

  • _MM_ROUND_NEAREST: (default) 四舍五入到最接近无限精度值。如果两个值相等接近,则四舍五入为偶数 (即,最低有效位将为零)。

  • _MM_ROUND_DOWN: 向负无穷大舍入。

  • _MM_ROUND_UP: 向正无穷大舍入。

  • _MM_ROUND_TOWARD_ZERO: 向零 (truncate) 舍入。

Example:

_MM_SET_ROUNDING_MODE(_MM_ROUND_DOWN)
Run

Denormals-are-zero/Flush-to-zero 模式

如果设置了此位,则将要反规范化的值将设置为零。默认情况下是关闭的。

您可以通过辅助函数 _MM_GET_FLUSH_ZERO_MODE()_MM_SET_FLUSH_ZERO_MODE() 读取和 enable/disable 此模式:

_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_OFF); // 关闭 (default)
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); // 打开
Run

Intel’s documentation