【问题标题】:Fast compare IEEE float greater than zero by cheating通过作弊快速比较大于零的 IEEE 浮点数
【发布时间】:2014-11-26 04:33:19
【问题描述】:

我在一个平台上工作,当将浮点数与零进行比较时,它会出现严重的停顿。作为优化,我看到使用了以下代码:

inline bool GreaterThanZero( float value )
{
   const int value_as_int = *(int*)&value;
   return ( value_as_int > 0 );
}

查看生成的程序集,停顿消失了,功能更高效。

这行得通吗?我很困惑,因为 IEEE 技巧的所有优化都使用了 SIGNMASKS 和大量的 AND/OR 操作(例如https://www.lomont.org/papers/2005/CompareFloat.pdf)。强制转换为带符号的 int 有帮助吗?在简单的线束中进行测试不会发现任何问题。

任何见解都会很好。

【问题讨论】:

  • 基本上,诀窍是检查高位。二进制补码表示中的非负整数的高位为 0,负整数为 1。很大程度上是巧合,同一位也用作 IEEE 浮点表示中的符号位。
  • 它可以工作,但编译器真的不会为像f > 0 这样简单的事情做最佳的事情吗?
  • @Barry 如果平台在比较 0f 时出现严重的停顿,那听起来不像我所知道的任何消费者平台。对我来说,这听起来像是一种特殊的硬件。
  • @Barry 这不是过早的优化;有了这个改变,代码运行得更快了,而且编译器不够聪明。我希望是的。比起修复由于与零比较而运行缓慢的 3D 重叠测试,我有更好的事情要担心!
  • @MarkRansom:他们不是。如果至少一个参数是 NaN,<<=>>=== 总是返回 false。 (实际上,再想十秒钟,他也没有实现比较!(x <= 0)。对于有限的xx > 0,对于某些NaN 是正确的,但对于其他NaN 不是。

标签: c++ optimization floating-point compare ieee


【解决方案1】:

表达式*(int*)&value > 0 测试value 是否为任何正浮点数,从最小的正非正规(与0x00000001 具有相同的表示)到最大的有限浮点(具有0x7f7fffff 的表示)和+inf (与0x7f800000 具有相同的表示形式)。该技巧将许多但不是全部的 NaN 表示(0x7f800001 上方的 NaN 表示)检测为正数。如果您不关心 NaN 的某些值使测试为真,那很好。

这一切都归功于 IEEE 754 格式的 representation

考虑到NaN 和带符号零的特殊行为,您在文献中看到的用于模拟 IEEE 754 操作的位操作函数可能旨在完美模拟。例如,*(int*)&value >= 0 的变体将不等于value >= 0.0f,因为-0.0f,表示为0x80000000 为无符号整数,因此-0x80000000 为有符号整数,使得后一个条件为真而前一个条件为真一假。这会使这些函数变得相当复杂。

投到签名的int 有帮助吗?

嗯,是的,因为floatint 的符号位在同一个位置,并且在未设置时都表示正数。但是条件value > 0.0f 也可以通过将value 重新解释为无符号整数来实现。


注意:将value 的地址转换为int* 违反了严格的别名规则,但如果您的编译器保证它为这些程序赋予意义(可能使用命令行选项),这可能是可以接受的。

【讨论】:

  • 如何转换为unsigned int 并检查它是否小于0x80000001u?另外,我认为让一个函数接收一个union 可能更清洁、更高效,它同时具有float 成员和int 成员,并且有一个转换浮点操作数并调用该函数的宏, 因为在许多平台上float 参数是在 FPU 寄存器中传递的,但这里需要整数形式的值。
  • @supercat 我看不出“转换为 unsigned int 并检查它是否小于 0x80000001u”如何接近于将使 f > 0 为 true 的浮点数与不为 true 的浮点数分开。跨度>
  • 它会选择负零,因为 >=0;它是否也获取 NaN 值取决于平台,但我怀疑在许多情况下负零会带来更大的问题。
  • @supercat 原来的问题是关于f > 0。我的回答中关于f >= 0 的评论仅此而已。
  • 明白了。对于严格大于零的测试,((unsigned)i-1u) < (0x7F800000-1u)) 怎么样?我认为这会将所有负数以及零和所有 NaN 都视为不大于零。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多