C/C++:浮点比较速度

Posted

技术标签:

【中文标题】C/C++:浮点比较速度【英文标题】:C/C++: Float comparison speed 【发布时间】:2011-01-15 01:00:41 【问题描述】:

我正在检查以确保浮点数不为零。浮点数不可能变为负数。那么这个float != 0.0f 还是这个float > 0.0f 更快?

谢谢。

编辑:是的,我知道这是微优化。但这每次都会在我的游戏循环中被调用,无论如何我都想知道。

【问题讨论】:

浮点数可以是负数。它们也可能在零附近呈片状。 微优化这个词浮现在脑海! 如果存在差异,可能会非常小,以至于您永远不会注意到差异。您是否分析过您的代码并发现这种特殊的比较是性能瓶颈?如果存在差异,也很可能是特定于体系结构和 CPU 的。您确定如果该值为零,那么它将完全为零吗?请记住,浮点计算通常是不精确的。除非您明确设置f = 0.0f;,否则您需要考虑计算错误。 @Jay:如果它们可以为零,那么它们很有可能是负数。即使数学上说它们应该等于 0,但浮点运算的现实意味着它可以非常接近于零,但在负数方面。 @Jay:作为一个游戏开发者,我要告诉你,如果你不知道如何确定要使用哪个版本,那么你的游戏就没有足够的高性能 需要知道。 始终编写最干净的代码。 永远不要编写“最快”的代码,因为在您拥有干净、可运行的程序之前,这无关紧要。你要快吗? int main() 。我保证这比你能写的任何东西都快。 “但它什么都做不了!”为快速而不是正确而编写的损坏代码也不是。 【参考方案1】:

在性能上不太可能存在可检测的差异。

【讨论】:

float > 0.0f,或者更好的float > EPSION更安全。【参考方案2】:

请考虑,仅供娱乐:

只有 2 个浮点值比较等于 0f:零和负零,它们仅相差 1 位。因此,测试 31 个非符号位是否清晰的电路/软件仿真就可以做到。

比较>0f稍微复杂一些,因为负数和0导致假,正数导致真,但NaN(两个符号的)也会导致假,所以它不仅仅是检查符号位.

根据浮点模式,任一操作都可能导致浮点寄存器在比较之前被舍入为 32 位的超精确结果,因此分数相等。

如果有任何区别,我有点希望!= 会更快,但我真的不希望有区别,我不会对某些特定的错误感到很惊讶实施。

我假设您的值不能为负的证明不受浮点错误的影响。例如,如果错误碰巧累积而不是取消,则沿1/2.0 - 1/3.0 - 1/6.00.4 - 0.2 - 0.2 的计算可能会导致正值或负值,因此大概不会发生类似的情况。关于与 0 相等的浮点测试的唯一实际用途是测试您是否为它分配了文字 0。或者其他一些计算的结果保证在float 中有结果0,但这可能很棘手。

【讨论】:

关于你的最后一段,通过反复乘以小于一的值来降低浮点数。 在硬件级别上,检查可以并行执行,因此两次检查将花费相同的时间。并且考虑到分支错误预测的代价要高得多,因此速度上不会有任何差异。 @ruslik:可以并行执行,还是保证并行执行?因此,速度不会有差异,还是速度很可能没有差异?换句话说,如果没有人可以提供一个速度不同的 C 实现,你会提供多大的可能性呢?你有信心提供 1000:1 吗?我的钱会花在软件浮动在相对简单的 CPU 上的东西上,比如早期的系列 ARM,作为最有可能产生差异的候选者。【参考方案3】:

如果不了解您的平台和编译器,就不可能给出明确的答案。 C 标准没有定义浮点数是如何实现的。

在某些平台上,是的,在其他平台上,不是。

如有疑问,请测量。

【讨论】:

【参考方案4】:

据我所知,f != 0.0f 有时会在您认为应该为假时返回真。

要检查浮点数是否非零,您应该执行Math.abs(f) > EPSILON,其中EPSILON 是您可以容忍的错误。

在此比较中,性能应该不是一个大问题。

【讨论】:

仅供参考,他说这个数字总是 >= 0 所以你不需要腹肌。【参考方案5】:

几乎可以肯定,在您有定量数据表明这是一个问题之前,您不应该进行这种微优化。如果你能证明这是一个问题,你应该弄清楚如何让你的编译器显示它正在生成的机器指令,然后获取该信息并转到你正在使用的处理器的数据手册,并查找所需的时钟周期数对于相同逻辑的替代实现。然后你应该再次测量以确保你看到了好处(如果有的话)。

如果您没有任何数据表明这是性能问题,请坚持使用最清晰、最简单地呈现您正在尝试执行的操作的逻辑的实现。

【讨论】:

以上是关于C/C++:浮点比较速度的主要内容,如果未能解决你的问题,请参考以下文章

C浮点精度[重复]

在混合 C/Fortran 代码中捕获浮点异常

在 C/C+ 中从 16 位线性 PCM 音频转换为 32 位浮点的最佳方法?

C/C++中如何判断浮点类型相等?

C/C++ 32位浮点型float转16进制并用字符串输出,简洁明了

如何在浮点数数组中创建一个由 1 组成的圆圈