C++ 移动或繁殖是否更快?为什么?
通常什么是更快的解决方案,乘法还是位移位 如果我想乘以10000,哪种代码会更快C++ 移动或繁殖是否更快?为什么?,c++,bit-shift,C++,Bit Shift,通常什么是更快的解决方案,乘法还是位移位 如果我想乘以10000,哪种代码会更快 v = (v<<13) + (v<<11) + (v<<4) - (v<<8); 问题的第二部分——如何找到乘法所需的最小移位数?我对乘以10000、1000和100很感兴趣。关于第一个问题:不用麻烦了。编译器知道得更好,并将根据各自的目标硬件对其进行优化 关于第二个问题:看看二进制表示: 例如:bin10000=0b10011100010000: 1 0 0
v = (v<<13) + (v<<11) + (v<<4) - (v<<8);
问题的第二部分——如何找到乘法所需的最小移位数?我对乘以10000、1000和100很感兴趣。关于第一个问题:不用麻烦了。编译器知道得更好,并将根据各自的目标硬件对其进行优化 关于第二个问题:看看二进制表示: 例如:bin10000=0b10011100010000:
1 0 0 1 1 1 0 0 0 1 0 0 0 0
13 12 11 10 9 8 7 6 5 4 3 2 1 0
所以你必须换13,10,9,8和4档。如果你想像你的问题那样通过减法来缩短连续的数字,你至少需要三个连续的数字才能得到任何东西
不过,还是让编译器来做吧。这是他的工作。这实际上取决于处理器的体系结构以及您使用的编译器 但您可以简单地查看每个选项的分解,并亲自查看 以下是我使用Visual Studio 2010奔腾编译器得到的结果:
int v2 = (v<<13) + (v<<11) + (v<<4) - (v<<8);
mov eax,dword ptr [v]
shl eax,0Dh
mov ecx,dword ptr [v]
shl ecx,0Bh
add eax,ecx
mov edx,dword ptr [v]
shl edx,4
add eax,edx
mov ecx,dword ptr [v]
shl ecx,8
sub eax,ecx
mov dword ptr [v2],eax
int v2 = 10000*v;
mov eax,dword ptr [v]
imul eax,eax,2710h
mov dword ptr [v2],eax
因此,在我的例子中,第二种选择似乎更快
顺便说一句,如果启用优化,您可能会得到不同的结果。我的矿山被禁用…只有一种情况下,轮班操作比*快,它由两个条件定义: 该操作的值幂为2 当你用分数相乘->除法。 让我们看得更深入一点: 乘法/除法、移位运算由硬件中的单位完成 建筑学通常有移位器、乘法器/除法器 执行这些操作,但每个操作都由 算术逻辑单元内的不同寄存器集。 二次幂的乘法/除法等于 左/右换档操作 如果不处理2的幂,则乘法和除法的执行方式略有不同: 乘法是由HW ALU单元根据数据类型在一个指令中执行的,但我们不要过分复杂 除法在循环中作为连续减法->多条指令执行 总结: 乘法只是一条指令;更换时 与一系列移位运算相乘是多重的 指令->第一个选项即使在并行计算机上也更快 建筑 二次幂的乘法与移位运算相同;编译器通常在代码中检测到移位时生成移位 除法是多重指令;用一系列的变化来重温这一点可能会更快,但这取决于每种情况 二次幂除法是多个操作,可以用一个右移操作代替;聪明的编译器会 自动执行此操作
较旧的Microsoft C编译器使用lea加载有效地址优化了移位序列,该地址允许5的倍数:
lea eax, DWORD PTR [eax+eax*4] ;eax = v*5
lea ecx, DWORD PTR [eax+eax*4] ;ecx = v*25
lea edx, DWORD PTR [ecx+ecx*4] ;edx = v*125
lea eax, DWORD PTR [edx+edx*4] ;eax = v*625
shl eax, 4 ;eax = v*10000
在我使用英特尔2600K 3.4ghz的系统上,乘法签名或无签名的速度更快。Visual Studio 2005和2012将v*10256相乘,然后减去v。问题第一部分的答案取决于处理器。为什么不把这个决定留给了解目标体系结构的编译器来做呢?编译器会一直以最快的方式来做吗?他并不是说他在优化代码,试着让你有限的思维去理解这样一个事实:有些人只是好奇,想学习,你知道,为了学习。@user4815162342是对的。这取决于机器。为了你,为什么不做一个基准测试。我想我已经来了。。。没有冒犯的意思。我完全理解想要学习。但“更快”是一个令人毛骨悚然的兔子洞,它不允许一个简单而令人满意的答案,只是它取决于在假设a和B的特定情况下X、Y、Z,[是/否]。唯一可行的方法是,1理解所有涉及的事情,从理论CS到机器代码和逻辑门及其相互作用,然后2使用逻辑和科学方法得出特定情况的答案。你问错问题了。谢谢,我想知道是否有算法可以找到这些问题。但如果你说编译器知道得最好,那我就把它留给他@KeluThatsall:关于算法,请参见编辑。这比你可能得到的要复杂得多。看起来是这样,我就让编译器按照他想要的方式去做;补充说明:如果启用优化,可能会得到不同的结果摘要点1的逻辑有错误。多条指令并不一定比执行完全不同操作的单个指令慢。不同的指令可能具有完全不同的延迟、吞吐量和管道行为。作为一个极端的例子,考虑登记器实际上是免费的,并且从RAM读取缓存,而没有缓存数百个周期。
可能吞吐量也会降低。我不想让事情变得过于复杂,也不想深入了解很多架构细节,但您可以放心地假设,对于这两种情况,相同的前提都是正确的;i、 e.无论执行多少条指令,您都可能遭受管道暂停、缓存未命中、高寄存器压力等问题。但是,当你把苹果和苹果进行比较时,给出同样的前提;on指令的执行速度比多条指令快,无论架构如何。
lea eax, DWORD PTR [eax+eax*4] ;eax = v*5
lea ecx, DWORD PTR [eax+eax*4] ;ecx = v*25
lea edx, DWORD PTR [ecx+ecx*4] ;edx = v*125
lea eax, DWORD PTR [edx+edx*4] ;eax = v*625
shl eax, 4 ;eax = v*10000
shl eax,4 ;ecx = v*(16)
mov ecx,eax
shl eax,4 ;ecx = v*(16-256)
sub ecx,eax
shl eax,3 ;ecx = v*(16-256+2048)
add ecx,eax
shl eax,2 ;eax = v*(16-256+2048+8192) = v*(10000)
add eax,ecx