避免C ++中的非规范值

经过长时间搜索性能问题后,我阅读了非正规浮点值。

显然,非标准化的浮点值可能是一个主要的性能问题,正如在这个问题中所说明的那样:为什么将0.1f更改为0会使性能下降10倍?

我有一个英特尔Core 2 Duo,并使用-O2编译gcc。

那么我该怎么做? 我能以某种方式指示g ++避免非正常值吗? 如果没有,我可以以某种方式测试一个float是否是非正常的?


你可以测试一个float是否使用denormal

#include <cmath>

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

(注意:我不确定这会在实践中全速执行。)

在C ++ 03中,这个代码在实践中为我工作,

#include <cmath>
#include <limits>

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

要决定在何处应用此功能,您可以使用Shark,VTune或Zoom等基于样本的分析器来突出显示由非正常值减缓的指令。 与其他优化相比,微观优化在没有前后分析的情况下完全没有希望。


等待。 在你做任何事情之前,你是否真的知道你的代码遇到了非规范化的值,并且他们正在产生可测量的性能影响?

假设你知道这一点,你知道你正在使用的算法是否稳定,如果denormal支持被关闭? 将错误答案提高10倍通常不是一个好的性能优化。

除了这些问题:

  • 如果你想检测非正常值来确认他们的存在,你有几个选择。 如果您有C99标准库或Boost,则可以使用fpclassify宏。 或者,您可以将您的数据的绝对值与最小正数正数进行比较。

  • 您可以设置硬件将非正常值清零(FTZ),或将非正常输入视为零(DAZ)。 最简单的方法,如果它在你的平台上得到了正确的支持,可能会在C头文件fenv.h使用fesetenv( )函数。 然而,这是C标准中支持得最少的特性之一,无论如何它本质上都是平台特定的。 您可能只想使用一些内联汇编来直接将FPU状态设置为(DAZ / FTZ)。


  • 大多数数学协处理器可以选择将非正规值截断为零。 在x86上,MXCSR控制寄存器中的FZ(清零)标志位。 检查您的CRT实现的支持功能以设置控制寄存器。 它应该在<float.h> ,类似于_controlfp()。 选项位通常在#defined符号中有“FLUSH”。

    设置完毕后请仔细检查数学结果。 无论如何,你应该这样做,得到非正常值是健康问题的一个标志。

    链接地址: http://www.djcxy.com/p/85511.html

    上一篇: Avoiding denormal values in C++

    下一篇: SQLite inserts wrapped in one transaction: no speed improvement