如何使 SIMD 除以零得到零? (x86-64)

问题描述 投票:0回答:1

我有一些想要除法的浮点数,其中一些可能是零。我怎样才能做到在 x86-64 上除以零时,只返回零而不是 NaN?

我尝试设置 MXCSR 的 FZ 和 DAZ 标志,但无济于事。我误解了什么吗?齐平到零 + 非正规数 零不应该被零除得到零吗?

#include <stdio.h>
#include <xmmintrin.h>

int main()
{
    #define CSR_FLUSH_TO_ZERO      (1 << 15)
    #define CSR_DENORMALS_ARE_ZERO (1 << 6)
    unsigned int csr = _mm_getcsr();
    csr |= CSR_FLUSH_TO_ZERO;
    csr |= CSR_DENORMALS_ARE_ZERO;
    _mm_setcsr(csr);

    __m128 a = { 0 };
    __m128 b = { 0 };
    a = _mm_div_ps(a, b);

    float f[4];
    _mm_store_ps(f, a);
    printf("%f\n", f[0]); // prints out 'nan'
}

https://godbolt.org/z/cfzPe5jcG

floating-point x86-64 simd sse divide-by-zero
1个回答
0
投票

没有 MXCSR 设置可以做到这一点,您需要额外的一对指令(

cmpps
andps
andnps
)来屏蔽除数输入为
==0.0f
的元素。

除以零会产生 +-无穷大,如果被除数也为零,则产生 NaN,因此刷新到零不会产生次正常输出。

启用 DAZ 将使

0 / subnornal
将次正常值完全视为
0.0f
并为您提供 NaN 而不是
0.0f
且除数为零。对于非零标准化股息,您仍然会溢出到+-无穷大。

FTZ(清零)仅在结果不正常时才执行任何操作。它禁用逐渐下溢;这是唯一发生刷新的情况,而不是其他会引发其他 FP 异常的情况。 DAZ(非正规数为零)只对次正规(又名非正规)做任何事情。

© www.soinside.com 2019 - 2024. All rights reserved.