Why does it require 20X more time for these calculations when the values get tiny
我是一个电路设计师,而不是软件工程师,所以我不知道如何追踪这个问题。
我正在处理一些IIR过滤器代码,当我通过过滤器处理非常小的值时,我遇到了执行速度非常慢的问题。为了找到问题,我编写了这个测试代码。
通常,循环将在大约200毫秒左右的时间内运行。(我没有测量它。)但是当testcheckbox->checked时,运行大约需要7秒。问题在于循环中A、B、C和D的大小减小,这正是IIR过滤器中输入变为零后的值所发生的情况。
我认为问题在于变量的exponent值小于-308。一个简单的修复方法是将变量声明为longdouble,但在实际代码中这不是一个简单的修复方法,而且看起来我不需要这样做。
你知道为什么会发生这种情况,还有什么简单的解决办法?
在它的情况下,我使用C++ Builder XE3。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | int j; double A, B, C, D, E, F, G, H; //long double A, B, C, D, E, F, G, H; // a fix A = (double)random(100000000)/10000000.0 - 5.0; B = (double)random(100000000)/10000000.0 - 5.0; C = (double)random(100000000)/10000000.0 - 5.0; D = (double)random(100000000)/10000000.0 - 5.0; if(TestCheckBox->Checked) { A *= 1.0E-300; B *= 1.0E-300; C *= 1.0E-300; D *= 1.0E-300; } for(j=0; j<=1000000; j++) { A *= 0.9999; B *= 0.9999; C *= 0.9999; D *= 0.9999; E = A * B + C - D; // some exercise code F = A - C * B + D; G = A + B + C + D; H = A * C - B + G; E = A * B + C - D; F = A - C * B + D; G = A + B + C + D; H = A * C - B + G; E = A * B + C - D; F = A - C * B + D; G = A + B + C + D; H = A * C - B + G; } |
编辑:正如答案所说,这个问题的原因是非正规数学,这是我从未听说过的。维基百科有一个很好的描述,就像sneftel给出的msdn文章一样。
http://en.wikipedia.org/wiki/denormal_编号
说了这句话,我仍然不能让我的代码刷新非正常值。msdn文章说要做到这一点:
1 | _controlfp(_DN_FLUSH, _MCW_DN) |
号
但是,这些定义不在XE3数学库中,所以我使用
1 | controlfp(0x01000000, 0x03000000) |
根据文章,但这对XE3没有影响。维基百科的文章中也没有建议的代码。
有什么建议吗?
你遇到了非正规数(小于
为了提高性能,可以通过调用
您已经进入了浮点下溢的领域,这会导致非规范化的数字——这取决于您可能陷入软件的硬件,而软件的速度要比硬件操作慢得多。