在 C/C++ 中乘以小数是否更快(与大数相反)?

Is it faster to multiply low numbers in C/C++ (as opposed to high numbers)?

问题示例:

计算 123 * 456 比计算 123456 * 7890 快吗?还是一样的速度?

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

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

对于至少达到体系结构字长的内置类型(例如现代 PC 上的 64 位,过去几十年中大多数 low-cost 通用 CPUs 上的 32 或 16 位) ,对于我听说过的每个 compiler/implementation/version 和 CPU, 用于乘以特定整数大小的 CPU 操作码需要一定数量的时钟周期与涉及的数量无关。不同大小的数据乘法,在某些CPUs 上表现不同(例如,AMD K7 对于 16 位 IMUL 有 3 个周期延迟,而对于 32 位有 4 个周期延迟)。

有可能在某些架构和compiler/flags组合上,像long long int这样的类型比CPU操作码有更多的位在一条指令中进行操作,因此编译器可能会发出代码来分阶段进行乘法运算,这将比 CPU-supported 类型的乘法运算慢。但同样,存储在 run-time 中的更宽类型的小值不太可能被处理 - 或执行 - 与较大的值有任何不同。

综上所述,如果一个或两个值是 compile-time 常量,编译器能够避免 CPU 乘法运算符并优化某些值的加法或位移运算符(例如 1 显然是一个 no-op,任何一方 0 ==> 0 结果,* 4 有时可以实现为 << 2)。没有什么特别的停止技术,比如用于较大数字的位移位,但是可以将较小百分比的此类数字优化到相同程度(例如,有更多的 2 的幂 - 可以使用向左位移位来执行乘法 - 0 到 1000 之间比 1000 到 2000 之间)。

对于所有意图和目的,相同的速度(即使计算速度存在差异,它们也是不可估量的)。如果您好奇,这里有一个基准测试不同的 CPU 操作:http://www.agner.org/optimize/instruction_tables.pdf.

这在很大程度上取决于处理器架构和型号。

在过去(大约 1980-1990 年),两个数字中的个数是一个因数 - 个数越多,相乘所需的时间越长[符号调整后,因此乘以 -1 是‘比乘以 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 位值慢一个或两个时钟周期。仅仅是因为现代处理器可以 "afford" 在一个周期内放下执行此操作的整个逻辑 - 无论是涉及晶体管本身的速度,还是这些晶体管占用的面积。

此外,在过去,经常有指令做 16 x 16 -> 32 位结果,但如果你想要 32 x 32 -> 32(或 64),编译器将不得不调用一个库函数 [或内联这样的函数]。今天,我不知道有任何现代高端处理器 [x86、ARM、PowerPC] 不能至少做到 64 x 64 -> 64,有些可以做到 64 x 64 -> 128,所有这些都在一条指令中(不是总是一个单一的周期')。

请注意,我完全忽略了 "if the data is in cache is an important factor" 这一事实。是的,这是一个因素 - 这有点像在以 200 km/h 行驶时忽略风阻 - 这根本不是你在现实世界中忽略的东西。然而,这对于本次讨论来说并不重要。就像制造跑车的人关心空气动力学一样,要使复杂 [或简单] 软件快速 运行 需要一定程度地关心 cache-content.