什么有更好的表现:乘法或除法?

时间:2012-10-19 15:02:27

标签: performance cpu low-level

哪个版本更快? x * 0.5 or x / 2

我不久前在大学开了一门叫做电脑系统的课程。从那时起,我记得用相对“简单”的逻辑门可以实现两个值的乘法,但除法不是“本机”操作,并且需要一个并数寄存器,该寄存器在除数中增加,并与除数相比较。

现在我必须优化具有大量分区的算法。不幸的是,它不仅仅是除以二,所以二元移位是没有选择的。将所有除法改为乘法会有所不同吗?

更新

我已经更改了我的代码而没有注意到任何差异。你可能正确的编译器优化。由于所有的答案都非常好,所以我对它们进行了全面的投票。我选择rahul的答案是因为它有很好的联系。

4 个答案:

答案 0 :(得分:6)

通常除法比乘法要贵得多,但智能编译器通常会将除法编译时常数转换为乘法。如果您的编译器不够智能,或者存在浮点精度问题,那么您可以始终明确地进行优化,例如:改变:

 float x = y / 2.5f;

为:

 const float k = 1.0f / 2.5f;

 ...

 float x = y * k;

请注意,这很可能是premature optimisation的情况 - 如果您已经对自己的代码进行了分析并确定将分部视为性能瓶颈,那么您应该只做这种事情。 < / p>

答案 1 :(得分:4)

除了整数和浮点数(它基本上可以转换为位移)的编译时常数除以2的幂是非常快的(相当于乘以编译时常量)

对于浮点数,即使用2的幂进行动态除法也比常规(动态或静态除法)快得多,因为它基本上变成了指数的减法。

在所有其他情况下,除法似乎比乘法慢几倍。

对于动态除数,我的 Intel(R)Core(TM)i5 CPU M 430 @ 2.27GHz 的缓慢因子似乎约为8,静态因子约为2。

结果来自我的一个小基准,我做了因为我对此有些好奇(注意两个权力的偏差):

enter image description here

enter image description here

  • ulong - 64位无符号
  • 标签中的
  • 1表示动态参数
  • 标签中的
  • 0表示静态已知的参数

结果来自以下bash模板:

#include <stdio.h>
#include <stdlib.h>
typedef unsigned long ulong;
int main(int argc, char** argv){
    $TYPE arg = atoi(argv[1]);
    $TYPE i = 0, res = 0;
    for (i=0;i< $IT;i++)
        res+=i $OP $ARG;
    printf($FMT, res);
    return 0;
}

分配$ -variables并使用-O3编译生成的程序并运行(动态值来自命令行,因为它很明显来自C代码)。

答案 2 :(得分:1)

这可能取决于您的特定CPU和参数类型。例如,在您的示例中,您正在进行浮点乘法,但是进行整数除法。 (至少,在大多数语言中我都知道使用C语法。)

如果您在汇编程序中工作,可以查看正在使用的具体说明并查看它们需要多长时间。

如果你没有在汇编程序中工作,你可能不需要关心。所有具有优化功能的现代编译器都会以这种方式将操作更改为最合适的指令。

你在优化方面取得的巨大成功不会像这样愚弄算术。相反,请关注您使用缓存的程度。考虑是否存在可能加速的算法更改。

答案 3 :(得分:1)

如果只是一次计算,你几乎不会发现任何差异,但如果你谈论数百万的交易,那么肯定分部比乘法更昂贵。你总是可以使用最清晰,最易读的东西。

请参阅此链接: - Should I use multiplication or division?