Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 移动或繁殖是否更快?为什么?_C++_Bit Shift - Fatal编程技术网

C++ 移动或繁殖是否更快?为什么?

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

通常什么是更快的解决方案,乘法还是位移位

如果我想乘以10000,哪种代码会更快

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