`isnan()` 和测试相等一样快吗?

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

在 C 中,测试一个浮点数是否为 NaN 与测试两个浮点数是否相等一样快吗?这就是

isnan()
与两个浮点之间的简单相等测试一样快吗?

我特别感兴趣的是在标准现代 Intel/AMD 平台上使用

gcc

这是一段 C 代码示例。

#include <math.h>
int main(double x)
{
  return isnan(x);
}
c optimization nan
4个回答
5
投票

在 x64 上使用 GCC,

math.h
isnan(float)
编译为

jmp __isnanf

使用尾部调用优化,但有效地调用函数。被调用的函数必须做一些相当于代码的事情,至少我没有看到任何更快的方法来实现它。然而,这留下了一个问题:它与比较结果相比如何。

但这并没有说明“测试浮点数是否为 NaN”有多快,因为执行此操作的方法不只有一种。最直接的方法

int isnan2(float x)
{
  return x != x;
}

实际上与比较 C 级别的浮点数是一样的。但 GCC 做到了:

xor eax, eax
ucomiss xmm0, xmm0
setp    al
ret

这与比较两个浮点数不太相同,但很接近,而且实际上更快一点。测试相等性意味着测试无序大小写,就像这里一样,但是 z 标志也必须测试,就像这样(再次来自 gcc)

xor eax, eax
mov edx, 1
ucomiss xmm0, xmm1
setp    al
cmovne  eax, edx
ret

奖励:使用

<cmath>
使
isnan
编译为与将浮点数与其自身进行比较相同的东西,请参阅链接的问题了解原因。

Godbolt 链接方便使用

我现在看到你实际上拥有了

double
,但这并没有从质上改变任何东西。


1
投票

问题是我们是否应该在代码中使用 NaN 以外的东西来表示未知值。 (OP评论

那么你应该将

isnan(x)
x == some_constant
进行比较。如果
some_constant
没有值 0 或 NAN,那么如果使用典型的 FP 表示,则比较可能只是位比较 - 在速度上很难击败它。

不过,NaN 更惯用。


0
投票

不。相等测试是内联的,因此您需要付出调用 isnan() 的函数调用开销的代价。但平等不能在没有 IEEE 的情况下使用,所以......


0
投票

对于 GCC(也许还有 Clang),优化

isnan()
函数调用的关键是代码中是否存在信号 NaN,以及在遇到信号 NaN 时是否会引发浮点异常。

GCC 默认情况下假定

-fno-signaling-nans
,因此
isnan(x)
可以安全地优化为
(x != x)
,在带有 SSE2 的 x86 上,它将转换为 UCOMISS 或 UCOMISD 指令。

设置

-fsignaling-nans
禁用此类优化。

ISO/IEC TS 18661-1(已纳入即将推出的 C23 标准)澄清了

isnan()
的行为,即该函数永远不会引发任何异常,即使参数是一个信号 NaN 时也是如此。 (讽刺的是,IEEE 754 中的“信号”NaN 并不总是发出信号。)

另一方面,当

(x != x)
为 sNaN 时,x 表达式
抛出 FP_INVALID 异常。

这里是“安静”NaN 和“信号”NaN 的各种表达式的行为的快速比较表:

              | isnan(x) | (x != x)  | (x >= x)   | isgreaterequal(x,x)
--------------+----------+-----------+------------+--------------------
-Wfloat-equal | no warn  | warn      | no warn    | no warn
--------------+----------+-----------+------------+--------------------
Finite number | false    | false     | true       | true
Infinity      | false    | false     | true       | true
NaN (quiet)   | true     | true      | FPE; false | false
SNaN          | true     | FPE; true | FPE; false | FPE; false

(表中“FPE”表示抛出浮点异常; 特别是“无效”例外。)

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