【发布时间】:2016-02-28 23:55:24
【问题描述】:
众所周知,除法比乘法需要更多的时钟周期来计算。 (参考这里的讨论:Floating point division vs floating point multiplication。)
我已经在我的 C++ 代码中使用 x * 0.5 代替 x / 2 和 x * 0.125 代替 x / 8,但我想知道我应该走多远。
对于反转时重复出现的小数(即1 / num 是重复出现的小数),我使用除法而不是乘法(例如x / 2.2 而不是x * 0.45454545454)。
我的问题是:在迭代次数相当多的循环中,我是否应该将除数替换为它们的重复乘法对应项(即x * 0.45454545454 而不是x / 2.2),还是这样带来更大的精度损失?
编辑:我做了一些分析,我在 Visual Studio 中开启了全面优化,使用 Windows QueryPerformanceCounter() 函数来获取分析结果。
int main() {
init();
int x;
float value = 100002030.0;
start();
for (x = 0; x < 100000000; x++)
value /= 2.2;
printf("Div: %fms, value: %f", getElapsedMilliseconds(), value);
value = 100002030.0;
restart();
for (x = 0; x < 100000000; x++)
value *= 0.45454545454;
printf("\nMult: %fms, value: %f", getElapsedMilliseconds(), value);
scanf_s("");
}
结果为:Div:426.907185ms,值:0.000000 乘法:289.616415ms,值:0.000000
除法所用的时间几乎是乘法的两倍,即使经过优化也是如此。性能优势是有保证的,但会降低精度吗?
【问题讨论】:
-
如果这是代码中的瓶颈,我会感到惊讶。你试过分析它吗?
-
你会失去一些精度。如果它对您有帮助的话,这是一个非常小的优化。
-
除法时间会随着使用的实际值而波动,也许乘法也会波动,因此为了公平比较,您应该从两个循环开始
value相同。 -
在没有任何上下文的情况下,编译器可以用一些关于无穷大、NaN 和负数的条件替换任何一个循环,然后是一个简单的
value = 0.0f;。
标签: c++ floating-point