在C / C ++中乘以低数字(而不是高数字)会更快吗?

时间:2018-03-08 06:50:59

标签: c++ c optimization integer-arithmetic

问题示例:

计算123 * 456比计算123456 * 7890快吗?还是速度相同?

我想知道32位无符号整数,但我不会忽略其他类型(64位,有符号,浮点等)的答案。如果不同,会有什么不同?这些位是否为0/1?

编辑:如果它有所不同,我应该澄清我指的是任何数字(两个低于100的随机数与两个高于1000的随机数)

3 个答案:

答案 0 :(得分:4)

对于内置类型至少达到架构的字大小(例如现代PC上的64位,过去几十年中大多数低成本通用CPU上的32位或16位),对于每个编译器/我听说过的实现/版本和CPU, 用于特定整数大小乘法的CPU操作码需要一定的时钟周期而不管涉及的数量 。不同大小的数据的乘法在某些CPU上的表现不同(例如,AMD K7对于16位IMUL有3个周期的延迟,而对于32位有4个周期)。

在某些架构和编译器/标志组合上,类似long long int的类型可能比CPU操作码在一条指令中可以操作的位数更多,因此编译器可能会发出用于分阶段进行乘法的代码,它比CPU支持的类型的乘法要慢。但同样,在更广泛类型的运行时存储的小值不太可能被处理 - 或执行 - 与更大的值不同。

所有这一切,如果一个或两个值是编译时常量,编译器就能够避免CPU乘法运算符并优化为某些值的加法或位移运算符(例如1显然是否-op,任一方0 ==&gt; 0结果,* 4有时可以实现为<< 2)。没有什么特别的停止技术,比如位移用于更大的数字,但是这些数字的较小百分比可以被优化到相同的程度(例如,有两个更多的权力 - 其中乘法可以是使用左移位进行 - 介于0和1000之间,而不是介于1000和2000之间)。

答案 1 :(得分:2)

这高度依赖于处理器架构和模型。

在过去(1980-1990)中,两个数字中的数字是一个因素 - 越多,经过符号调整后乘以的时间越长,所以乘以-1不是&#39 ; t慢于乘以1,但乘以32767(15个)明显慢于乘以17(2个)]。这是因为乘法基本上是:

unsigned int multiply(unsigned int a, unsigned int b)
{  
    res = 0;  
    for(number of bits)
    {
        if (b & 1)
        {
           res += a;
        }
        a <<= 1;
        b >>= 1;
    }
}

在现代处理器中,乘法无论哪种方式都相当快,但64位乘法可以是一个时钟周期,也可以比32位值慢两倍。仅仅因为现代处理器可以承受&#34;在单个周期中放下完成这个的整个逻辑 - 无论是在晶体管本身的速度,还是晶体管占用的区域。

此外,在过去,经常有指示做16 x 16 - &gt; 32位结果,但如果您想要32 x 32 - > 32(或64),编译器必须调用库函数[或内联这样的函数]。今天,我不知道任何现代高端处理器[x86,ARM,PowerPC]至少不能做64 x 64 - &gt; 64,有些做64 x 64 - &gt; 128,所有这些都在一条指令中(并不总是单个循环)。

请注意,我完全忽略了这样一个事实,即如果数据在缓存中是一个重要因素&#34;。是的,这是一个因素 - 它有点像在以200公里/小时的速度行驶时忽略风阻 - 它根本不是你在现实世界中忽视的东西。但是,这对于这次讨论来说并不重要。就像制造跑车关心空气动力学的人一样,让复杂(或简单)的软件快速运行需要一定程度的关注缓存内容。

答案 2 :(得分:-3)

对于所有意图和目的,速度相同(即使计算速度存在差异,它们也是无法估量的)。如果您有好奇心,请参考以下不同CPU操作的参考:http://www.agner.org/optimize/instruction_tables.pdf