将非规范化数字刷新为零

Posted

技术标签:

【中文标题】将非规范化数字刷新为零【英文标题】:Flushing denormalised numbers to zero 【发布时间】:2012-07-26 14:23:32 【问题描述】:

我已经在网上搜索无济于事。

Xcode 和 Visual C++ 有没有办法将非规范化的数字视为 0?我原以为IDE首选项中有一个选项可以打开此选项,但似乎找不到。

我正在做一些跨平台的音频工作,需要阻止某些处理器占用资源。

干杯

【问题讨论】:

【参考方案1】:

您正在寻找一种平台定义的方式来在 MXCSR 寄存器中设置 FTZ 和/或 DAZ(在带有 SSE 或 x86-64 的 x86 上);见https://***.com/a/2487733/567292

通常这被称为_controlfp; Microsoft 文档位于 http://msdn.microsoft.com/en-us/library/e9b52ceh.aspx

您还可以使用_MM_SET_FLUSH_ZERO_MODE 宏:http://msdn.microsoft.com/en-us/library/a8b5ts9s(v=vs.71).aspx - 这可能是最跨平台的可移植方法。

【讨论】:

您还需要设置 Visual Studio 编译器标志才能使用 sse: "/arch:sse2"【参考方案2】:

为了在全局范围内禁用非规范化,我使用以下 2 个宏:

//warning these macros has to be used in the same scope
#define MXCSR_SET_DAZ_AND_FTZ \
int oldMXCSR__ = _mm_getcsr(); /*read the old MXCSR setting */ \
int newMXCSR__ = oldMXCSR__ | 0x8040; /* set DAZ and FZ bits */ \
_mm_setcsr( newMXCSR__ ); /*write the new MXCSR setting to the MXCSR */ 

#define MXCSR_RESET_DAZ_AND_FTZ \
/*restore old MXCSR settings to turn denormals back on if they were on*/ \
_mm_setcsr( oldMXCSR__ ); 

我在流程开始时调用第一个,在结束时调用第二个。 不幸的是,这似乎不适用于 Windows。

要在本地刷新非正规我使用这个

const Float32 k_DENORMAL_DC = 1e-25f;
inline void FlushDenormalToZero(Float32& ioFloat) 
 
    ioFloat += k_DENORMAL_DC;
    ioFloat -= k_DENORMAL_DC;    
 

【讨论】:

【参考方案3】:

为此,请在程序启动期间使用英特尔内部宏。例如:

#include <immintrin.h> 
int main() 
  _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); 

在我的 MSVC 版本中,这发出了以下汇编代码:

    stmxcsr DWORD PTR tv805[rsp]
    mov eax, DWORD PTR tv805[rsp]
    bts eax, 15
    mov DWORD PTR tv807[rsp], eax
    ldmxcsr DWORD PTR tv807[rsp]

MXCSR 是控制和状态寄存器,此代码设置第 15 位,打开 清零模式

需要注意的一点:这只影响计算产生的非规范化。如果您还想将非正规数设置为零(如果它们用作输入),您还需要使用以下命令设置 DAZ 标志(非正规数为零):

_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);

更多信息请参见https://software.intel.com/en-us/cpp-compiler-developer-guide-and-reference-setting-the-ftz-and-daz-flags。

另请注意,您需要为每个线程设置 MXCSR,因为包含的值是每个线程的本地值。

【讨论】:

以上是关于将非规范化数字刷新为零的主要内容,如果未能解决你的问题,请参考以下文章

将非规范化文件中的数据加载到规范化表中

将非规范化数据加载到数据仓库中

如何将非规范化表映射到两个实体?

将非规范化表转换为嵌套结构

清除表中的所有行,将标识规范重置为零并且不影响外键?

在 python 浮点数中刷新为零和/或有效数字