Performance 什么性能更好:乘法还是除法?

Performance 什么性能更好:乘法还是除法?,performance,cpu,low-level,Performance,Cpu,Low Level,哪个版本更快? x*0.5 或 x/2 不久前,我在大学上了一门叫做计算机系统的课程。从那时起,我记得两个值相乘可以用比较“简单”的逻辑门实现,但除法不是“本机”运算,需要一个和寄存器,它在一个循环中由除数增加,并与被除数进行比较 现在我必须优化一个有很多分割的算法。不幸的是,它不只是除以2,所以二进制移位是没有选择的。将所有除法都改为乘法会有不同吗 更新: 我已经更改了代码,没有注意到任何差异。关于编译器优化,您可能是对的。因为所有的答案都很好,我把它们都投了赞成票。我选择rahul的答案是因

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

不久前,我在大学上了一门叫做计算机系统的课程。从那时起,我记得两个值相乘可以用比较“简单”的逻辑门实现,但除法不是“本机”运算,需要一个和寄存器,它在一个循环中由除数增加,并与被除数进行比较

现在我必须优化一个有很多分割的算法。不幸的是,它不只是除以2,所以二进制移位是没有选择的。将所有除法都改为乘法会有不同吗

更新:


我已经更改了代码,没有注意到任何差异。关于编译器优化,您可能是对的。因为所有的答案都很好,我把它们都投了赞成票。我选择rahul的答案是因为这个链接很好

通常除法要比乘法昂贵得多,但智能编译器通常会将编译时常数的除法转换为乘法。如果您的编译器不够智能,或者存在浮点精度问题,则始终可以显式执行优化,例如更改:

 float x = y / 2.5f;
致:


请注意,这很可能是一种情况-如果您已经分析了代码,并且肯定了除法是一个性能瓶颈,那么您应该只做这种事情。

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

如果您在汇编程序中工作,您可以查找正在使用的特定指令,并查看它们需要多长时间

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


你在优化上的巨大胜利不会来自于像这样玩弄算术。相反,请关注缓存的使用情况。考虑是否有算法改变可能加速事情。

< P>如果它是一个单独的计算,你几乎察觉不到任何差异,但是如果你谈论了数百万的事务,那么肯定的划分比乘法更昂贵。你总是可以使用最清晰易读的东西


请参考此链接:-

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

对于浮点运算,即使是二次幂的动态除法也比常规除法(动态或静态除法)快得多,因为它基本上变成了指数的减法

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

对于动态除数,我的Intel(R)Core(TM)i5CPU M430@2.27GHz的慢降因子似乎约为8,对于静态除数,慢降因子约为2

结果来自我的一个小基准,我之所以这样做是因为我对此有点好奇(注意二次方的畸变):

  • 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;
}
#包括
#包括
typedef无符号长ulong;
int main(int argc,字符**argv){
$TYPE arg=atoi(argv[1]);
$TYPE i=0,res=0;
对于(i=0;i<$IT;i++)
res+=i$OP$ARG;
printf($FMT,res);
返回0;
}

分配$-变量,使用
-O3
编译生成的程序并运行(动态值来自命令行,这在C代码中很明显)。

如果执行1mil操作循环并计时,我想你可以这样得到答案:浮点乘法和除法可能同样快。我怀疑整数的乘法速度要快得多。此外,整数运算往往比FP运算快。换句话说,iMult-ffast math,编译器通常不允许为您执行此操作。如果没有-ffast math for divide for two,可能会发生这种情况,因为e
0.5f
是可精确表示的,但不是常数除数(和大多数常数)在不改变结果的情况下,绝对无法做到这一点。顺便说一句,是的,gcc会对2的幂进行计算。这还取决于常数和精度保证。在数学意义上,您可以将x/10.0转换为x*0.1。在二进制浮点算术中,您可能会失去精度,因为0.1是二进制形式的周期数,因此需要be四舍五入。数字10不会出现这种情况。您可以在那里看到一个示例:在某些情况下,进一步四舍五入可以解决差距,在某些情况下,则不会。当然,编译器可以
#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;
}