哪一个更快 -
val = val*10;
或
val = (val<<3) + (val<<2);
与移位指令相比,imul
需要多少个时钟周期?
答案 0 :(得分:60)
这是21世纪。现代硬件和编译器知道如何生成高度优化的代码。使用shift来编写乘法将无助于提高性能,但它可以帮助您生成带有错误的代码。
您已经使用代码乘以12而不是10来证明这一点。
答案 1 :(得分:10)
我会说,只需编写val = val * 10;
或val *= 10;
,让编译器担心这些问题。
答案 2 :(得分:8)
在这种情况下,它们可能需要相同的循环次数,尽管您的手动“优化”需要多一个寄存器(这可能会减慢周围的代码):
val = val * 10;
lea (%eax,%eax,4),%eax
add %eax,%eax
VS
val = (val<<3) + (val<<1);
lea (%eax,%eax,1),%edx
lea (%edx,%eax,8),%eax
编译器知道如何做strength reduction,可能比你好得多。此外,当您将代码移植到其他平台(例如,ARM)时,编译器也知道如何在该平台上减少强度(x86的LEA
提供的优化机会不同于ARM的ADD
和{{1} }})。
答案 3 :(得分:3)
用高级语言手工制作这样愚蠢的“优化”,除了向人们展示你与现代技术和编程实践脱节之外什么都不会做。
如果你直接在汇编中写作,那么担心这一点是有意义的,但你不是。
说到这里,有一些很少的情况,编译器将无法优化这样的东西。考虑一组可能的乘法因子,每个因子恰好由2个非零位组成,代码如下:
x *= a[i];
如果分析显示这是您程序中的主要瓶颈,您可以考虑将其替换为:
x = (x<<s1[i]) + (x<<s2[i]);
只要您计划测量结果。但是我怀疑很难找到这种情况有用的情况,或者甚至可能发生的情况。与移位和总指令吞吐量相比,在具有弱乘法单元的CPU上,这是合理的。