这个问题在这里已经有一个答案:>
Is multiplication and division using shift operators in C actually faster?14个
可以这样做的时候,我想知道用一个位移替换单个乘法后跟一个整数除法是否更快.说我有一个int k,我想要乘以2.25.
可以这样做的时候,我想知道用一个位移替换单个乘法后跟一个整数除法是否更快.说我有一个int k,我想要乘以2.25.
什么更快?
- int k = 5;
- k *= 2.25;
- std::cout << k << std::endl;
要么
- int k = 5;
- k = (k<<1) + (k/4);
- std::cout << k << std::endl;
产量
- 11
- 11
两者都给出相同的结果,可以查看this full example.
解决方法
第一次尝试
我定义函数regularmultiply()和bitwisemultiply(),如下所示:
- int regularmultiply(int j)
- {
- return j * 2.25;
- }
- int bitwisemultiply(int k)
- {
- return (k << 1) + (k >> 2);
- }
在使用仪器进行分析时(在2009年Macbook OS X 10.9.2中的XCode中),似乎比常规执行的速度要快两倍.
汇编代码输出似乎证实了这一点,因为大部分时间花费大部分时间用于注册改组和函数返回,而常规的大部分时间都花费在乘法上.
regularmultiply:
bitwisemultiply:
但我的审判时间太短.
第二次尝试
接下来,我尝试使用1000万次乘法执行这两个函数,这次将循环放在函数中,以便所有的函数进入和离开都不会掩盖数字.而这一次,结果是每个方法花了大约52毫秒的时间.因此,至少对于相对较大而不是巨大的计算量,这两个功能大致相同.这让我感到惊讶,所以我决定计算更长和更大的数字.
第三次尝试
这一次,我只有1亿,通过5亿加倍2.25,但比特比实际上出来比普通比较慢.
最后的尝试
最后,我切换了这两个功能的顺序,只是为了看看Instrument中不断增长的cpu图表可能会减慢第二个功能.但是,经常性的表现略好一些:
这是最后的程序是什么样的:
- #include <stdio.h>
- int main(void)
- {
- void regularmultiplyloop(int j);
- void bitwisemultiplyloop(int k);
- int i,j,k;
- j = k = 4;
- bitwisemultiplyloop(k);
- regularmultiplyloop(j);
- return 0;
- }
- void regularmultiplyloop(int j)
- {
- for(int m = 0; m < 10; m++)
- {
- for(int i = 100000000; i < 500000000; i++)
- {
- j = i;
- j *= 2.25;
- }
- printf("j: %d\n",j);
- }
- }
- void bitwisemultiplyloop(int k)
- {
- for(int m = 0; m < 10; m++)
- {
- for(int i = 100000000; i < 500000000; i++)
- {
- k = i;
- k = (k << 1) + (k >> 2);
- }
- printf("k: %d\n",k);
- }
- }
结论
那么我们可以说这一切呢?有一点我们可以肯定地说,优化编译器比大多数人更好.此外,当有很多计算时,这些优化显示出更多的优势,这是您真正想要优化的唯一时间.因此,除非您在汇编中编码优化,否则将乘法更改为位移可能不会有太大帮助.
考虑应用程序的效率总是很好,但微型效率的提高通常不足以保证您的代码不易读取.