浮点C ++编译器选项|防止A / B - >一个*(1 / B)
-
25-09-2019 - |
题
我写的实时数字软件,在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,但在理论上它究竟存在微调优化。
可以把含有这些计算的功能在一个单独的源代码文件和编译仅与所述不同的设置文件?
我不知道这是否是安全的,虽然,你需要检查!