这个问题在这里已经有一个答案:>
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); } }
结论
那么我们可以说这一切呢?有一点我们可以肯定地说,优化编译器比大多数人更好.此外,当有很多计算时,这些优化显示出更多的优势,这是您真正想要优化的唯一时间.因此,除非您在汇编中编码优化,否则将乘法更改为位移可能不会有太大帮助.
考虑应用程序的效率总是很好,但微型效率的提高通常不足以保证您的代码不易读取.