当我阅读 C 中的技巧时,我在这里看到了这个技巧http://www.cprogramming.com/tips/tip/multiply-rather-than-divide 但我不确定。有人告诉我,乘法和除法都较慢且耗时,并且需要很多周期。
而且我看到人们经常使用i << 2
而不是i x 4
因为换档更快。
使用它是一个很好的提示x0.5 or /2
吗?还是现代编译器确实以更好的方式对其进行了优化?
当我阅读 C 中的技巧时,我在这里看到了这个技巧http://www.cprogramming.com/tips/tip/multiply-rather-than-divide 但我不确定。有人告诉我,乘法和除法都较慢且耗时,并且需要很多周期。
而且我看到人们经常使用i << 2
而不是i x 4
因为换档更快。
使用它是一个很好的提示x0.5 or /2
吗?还是现代编译器确实以更好的方式对其进行了优化?
确实,某些(如果不是大多数)处理器的倍增速度比执行除法运算要快,但是,这就像++i
比i++
for 循环更快的神话。是的,它曾经是,但现在,编译器足够聪明,可以为你优化所有这些东西,所以你不应该再关心这个了。
关于移位,曾经移位<< 2
比乘以 4 更快,但那些日子已经结束,因为大多数处理器可以在一个时钟周期内进行乘法运算,就像移位操作一样。
一个很好的例子是在 VGA320x240
模式下计算像素地址。他们都这样做了:
address = x + (y << 8) + (y << 6)
将 y 乘以 320。在现代处理器上,这可能比仅执行以下操作要慢:
address = x + y * 320;
所以,只要写下你的想法,编译器会做剩下的:)
我发现这项服务对于测试这类东西非常宝贵:
看看最后的组装。99% 的情况下,您会看到编译器将其全部优化为相同的代码。不要浪费脑力!
在某些情况下,最好明确地编写它。例如,2^n
(其中 n 是一个正整数)可以写成,(int) pow( 2.0, n )
但显然更好用1<<n
(并且编译器不会为您进行优化)。因此,将这些事情留在您的脑海中是值得的。与任何事情一样,不要过早优化。
“乘以 0.5 而不是除以 2”(2.0)现在在更少的环境中比以前更快,这主要是由于改进的编译器可以优化代码。
出于类似的原因,“使用 i << 2 而不是 ix 4”在较少的环境中更快。
在某些情况下,程序员仍然需要处理此类问题,但这种情况越来越少。代码维护作为一个主要问题继续增长。因此,请使用对该代码片段最有意义的内容:x*0.5
、x/2.0
、half(x)
等。
编译器很容易优化代码。建议您在编写代码时考虑到高级问题。例如。算法是 O(n) 还是 O(n*n)?
要传递的重要思想是最佳代码设计实践不断发展,环境之间会发生变化。适应性强。今天最好的东西可能会在未来发生变化(或成倍增加)。
许多 CPU 可以在 1 或 2 个时钟周期内执行乘法,但除法总是需要更长的时间(尽管 FP 除法有时比整数除法更快)。
如果您查看此答案,如何比较 C++ 中 log() 和 fp 除法的性能?您会看到除法可以超过 24 个周期。
为什么除法比乘法花这么多时间?如果您还记得小学时,您可能还记得乘法基本上可以通过许多同时加法来执行。除法需要迭代减法,不能同时执行,因此需要更长的时间。事实上,一些 FP 单元通过执行倒数近似并乘以它来加速除法。它不太准确,但速度更快。
如果您正在使用整数,并且您希望得到一个整数作为结果,最好使用/ 2
,这样可以避免不必要的与浮点数的转换