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

Is `isnan()` as fast as testing equality?

在 C 中,测试一个浮点数是否为 NaN 是否与测试两个浮点数是否相等一样快?也就是说 isnan() 和两个浮点数之间的简单相等性测试一样快?

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

这是一段 C 代码示例。

#include <math.h>
int main(double x)
{
  return isnan(x);
}

没有。相等性测试是内联的,因此您需要为调用 isnan() 的函数调用开销付出代价。但是equality不能用w/o IEEE,所以...

在 x64 上使用 GCC,math.hisnan(float) 编译为

jmp __isnanf

使用尾调用优化,但有效地调用了一个函数。被调用的函数将不得不做一些相当于代码的事情,至少我没有看到任何更快的实现它的方法。然而,这留下了一个问题,即它与未回答的比较相比如何。

但这并没有说明 "testing if a float is 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 link for convenience

我现在看到你实际上有 double,但这并没有改变任何质量。

The question is if we should use something other than NaN in our code to represent unknown values. ()

那你应该比较一下isnan(x)x == some_constant。如果 some_constant 的值不是 0 或 NAN,那么如果使用典型的 FP 表示,则比较可以简单地进行位比较——在速度方面很难超过它。

不过,NaN 更加地道。