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

Rap*_*ael 4 c optimization nan

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

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

这是一段 C 代码示例。

#include <math.h>
int main(double x)
{
  return isnan(x);
}
Run Code Online (Sandbox Code Playgroud)

har*_*old 6

在 x64 上使用 GCC,math.h编译isnan(float)

jmp __isnanf
Run Code Online (Sandbox Code Playgroud)

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

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

int isnan2(float x)
{
  return x != x;
}
Run Code Online (Sandbox Code Playgroud)

从字面上看与比较 C 级别的浮点数是一样的。但 GCC 是这样做的:

xor eax, eax
ucomiss xmm0, xmm0
setp    al
ret
Run Code Online (Sandbox Code Playgroud)

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

xor eax, eax
mov edx, 1
ucomiss xmm0, xmm1
setp    al
cmovne  eax, edx
ret
Run Code Online (Sandbox Code Playgroud)

奖励:使用<cmath>makeisnan编译的结果与将浮点数与其自身进行比较相同,请参阅链接的问题了解原因。

Godbolt 链接以方便使用

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

  • @eleanora 不,因为并非所有人都支持 NaN。有些平台根本没有 NaN(例如 TI-83+、某些 DSP 等)。如果您使用 -ffast-math 或一些相关选项,它也不起作用 - 它们会破坏各种各样的东西,通常包括这个。 (2认同)