我写的实时数字软件,在C ++中,目前使用Visual-C ++编译2008年它。 现在,使用“快速”浮点模型(/fp:fast),各种优化,其中大多数是有用的我的情况下,但具体是:

a/b -> a*(1/b) Division by multiplicative inverse

太数值不稳定对一批量我的计算。

(参见:的Microsoft Visual C ++浮点优化

切换到/fp:precise让我的应用程序运行不止慢一倍。是能够任意微调优化(即,禁止该特定优化),或以某种方式手动旁路它?

- 实际的最小码例如: -

void test(float a, float b, float c,
    float &ret0, float &ret1) {
  ret0 = b/a;
  ret1 = c/a;
} 

[我的实际代码是大多矩阵相关算法]

输出:VC(CL,版本15,0x86可以)是:

divss       xmm0,xmm1 
mulss       xmm2,xmm0 
mulss       xmm1,xmm0 

有一个DIV,而不是两个,是一个大问题数值,(XMM0,预装了来自RAM 1.0F),因为这取决于xmm1,2的值(这可能是在不同的范围),你可能会失去很多的精度(不SSE编译,输出相似的堆叠的x87-FPU代码)。

与环绕功能

#pragma float_control( precise, on, push )
...
#pragma float_control(pop)

确实解决精度问题,但是首先,这是仅在功能级(全球范围)可用的,并且第二,它可以防止内联函数的,(即,速度处罚太高)

“精确”的输出被强制转换为“双”来回阱:

 divsd       xmm1,xmm2 
 cvtsd2ss    xmm1,xmm1 
 divsd       xmm1,xmm0 
 cvtpd2ps    xmm0,xmm1 
有帮助吗?

解决方案 5

(奇怪的)的解决方案,我已发现:当通过在函数相同的值除以 - 添加一些小量:

    a/b; c/b 

- >

    a/(b+esp1); c/(b+esp2)

另外,通过零

可以节省从偶尔DIV

其他提示

添加

#pragma float_control( precise, on)

的计算之前和

#pragma float_control( precise,off)

后。我认为应该这样做。

该文献指出,可以控制使用编译指示的线由行基础浮子指向的优化。

还有__assume。您可以使用__assume(A / B!=(A *(1 / B)))。我从来没有实际使用__assume,但在理论上它究竟存在微调优化。

可以把含有这些计算的功能在一个单独的源代码文件和编译仅与所述不同的设置文件?

我不知道这是否是安全的,虽然,你需要检查!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top