在C++中避免使用非规范化的值

15 浏览
0 Comments

在C++中避免使用非规范化的值

在寻找性能缺陷的过程中,我长时间阅读了关于非规范浮点值的内容。显然,非规范化的浮点值可能是一个重大的性能问题,正如这个问题所示:为什么将 0.1f 改为 0 会使性能下降10倍?我使用的是 Intel Core 2 Duo 处理器,并且使用 gcc 进行编译,使用了 -O2 选项。那么我该怎么办呢?我能否以某种方式告诉 g++ 避免非规范值?如果不能,我能以某种方式测试一个 float 是否是非规范的吗?

0
0 Comments

避免在C++中出现非规范化值

在C++中,避免出现非规范化值是一个重要的问题。非规范化值是指浮点数中指数部分为0的情况,这种情况下浮点数的表示不再遵循IEEE 754标准。出现非规范化值可能会导致计算结果不准确,甚至引发程序崩溃。

为了避免出现非规范化值,我们可以使用数学协处理器的选项来将这些值截断为零。在x86架构中,可以通过设置MXCSR控制寄存器中的FZ(Flush to Zero)标志来实现。可以在CRT实现中查找支持设置控制寄存器的函数,通常可以在中找到类似_controlfp()的函数。该选项位通常在宏定义符号中包含"FLUSH"。

在设置了这个选项后,务必再次检查数学计算的结果。无论是否出现非规范化值,检查计算结果都是一个良好的习惯,可以帮助我们发现和解决健康问题。

0
0 Comments

避免C++中的非规范化值的问题出现的原因及解决方法

在开始之前,请确认您的代码是否真的遇到了非规范化值,并且它们对性能有可测量的影响吗?

假设您已经知道了这一点,那么您是否知道您正在使用的算法在关闭非规范化支持时是否稳定?以10倍速度得到错误的答案通常不是一个好的性能优化。

除了这些问题之外:

- 如果您想要检测非规范化值以确认其存在,您有几个选择。如果您有C99标准库或Boost库,您可以使用fpclassify宏。或者,您可以将您的数据的绝对值与最小的正规数进行比较。

- 您可以将硬件设置为将非规范化值转换为零(FTZ),或将非规范化输入视为零(DAZ)。如果在您的平台上完全支持,最简单的方法可能是使用C头文件fenv.h中的fesetenv()函数。然而,这是C标准中支持最少的功能之一,而且本质上是平台特定的。您可能想要使用一些内联汇编来直接设置FPU状态为(DAZ/FTZ)。

以上是避免C++中的非规范化值的问题出现的原因及解决方法。

0
0 Comments

避免在C++中出现非规格化值(Avoiding denormal values in C++)

在C++中,有时候会遇到处理非规格化值(denormal values)的情况。这些非规格化值是指浮点数中的一种特殊情况,其值非常接近于零,但不等于零。处理非规格化值可能会导致性能下降,因此需要采取相应的措施来避免这种情况。

判断一个浮点数是否为非规格化值可以使用以下代码:

#include 
if ( std::fpclassify( flt ) == FP_SUBNORMAL )

需要注意的是,上述代码在实际中可能执行速度不够快。

在C++03中,下面的代码对我来说是有效的:

#include 
#include 
if ( flt != 0 && std::fabsf( flt ) < std::numeric_limits::min() ) {
    // it's denormalized
}

这段代码可以判断一个浮点数是否为非规格化值。需要注意的是,为了确定在哪里应用这段代码,可以使用一种基于样本的分析工具(如Shark、VTune或Zoom)来标记由非规格化值导致的指令速度变慢的情况。在进行微优化时,尤其是在其他优化之前和之后,分析是非常重要的。

关于性能惩罚的问题,你确定吗?我写了一个小测试程序,显示当浮点数的值为exp(-100)时,相加的速度比值为0.1时慢10倍。我完全错了吗?

答案是不完全错,性能惩罚实际上要比10倍大得多。

使用std::isnormal在大多数情况下不能达到你想要的效果,因为isnormal在其参数为零、无穷大或NaN时返回0(在寻找非规格化值时,通常只关注非规格化值,而不是那些在现代硬件上以高速处理的其他值)。

哎呀,零是真正的破坏者。谢谢提醒。

上述答案可以检测到非规格化值,但不是避免性能惩罚的好方法。更好的方法是设置浮点数单元的控制标志,以清除非规格化值,就像其他人提到的那样。

0