将非规范化数字刷新为零

时间:2012-07-26 14:23:33

标签: c++ xcode visual-studio-2010 audio

我在网上搜索无济于事。

Xcode和Visual C ++是否有办法将非规范化数字视为0?我原本以为IDE首选项中有一个选项可以启用此选项,但似乎无法找到它。

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

干杯

3 个答案:

答案 0 :(得分:9)

您正在寻找一种平台定义的方法来在MXCSR寄存器中设置FTZ和/或DAZ(在x86上使用SSE或x86-64);见https://stackoverflow.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 - 这可能是最具跨平台的便携式方法。

答案 1 :(得分:4)

为了全局禁用非正规,我使用这两个宏:

//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;    
} 

答案 2 :(得分:0)

为此,请在程序启动过程中使用Intel Intrinsics宏。例如:

#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位设置为1,这将打开清零模式

需要注意的一件事:这只会影响计算导致的异常。如果您还想将反常数用作 input 时将其设置为零,则还需要使用以下命令设置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,因为其中包含的值是每个线程本地的。