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

lhk*_*lhk 4 cpu performance low-level

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

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

现在我必须优化一个有很多划分的算法.不幸的是,它不仅仅是除以二,所以二元移位是没有选择的.将所有分区改为乘法会有所不同吗?

更新:

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

PSk*_*cik 7

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

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

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

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

结果来自我的一个小基准,这是我做的,因为我对此有点好奇(注意 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;
}
Run Code Online (Sandbox Code Playgroud)

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

  • 仅供参考,已知整数和浮点乘法和加法的吞吐量和延迟在现代 x86 CPU(包括您的 Intel Nehalem)上是恒定的(而不是数据相关的)。已知除法性能依赖于数据(并且仅部分流水线化)。这是一个有趣的测试,测试哪些实际数据在 [Agner Fog 的指令表](http://www.agner.org/optimize/) 范围的下限或上限处产生吞吐量。请注意,64 位除法比 64 位乘法慢得多,比 32 位乘法要慢得多。您的测试中“ulong”的尺寸是多少? (2认同)

Pau*_*l R 6

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

 float x = y / 2.5f;
Run Code Online (Sandbox Code Playgroud)

至:

 const float k = 1.0f / 2.5f;

 ...

 float x = y * k;
Run Code Online (Sandbox Code Playgroud)

请注意,这很可能是过早优化的情况- 如果您已经对代码进行了分析并确定将分部视为性能瓶颈,那么您应该只做这种事情.


Rah*_*thi 4

好吧,如果这是一次计算,您几乎不会注意到任何差异,但如果您谈论数百万笔交易,那么除法肯定比乘法成本更高。您始终可以使用最清晰易读的内容。

请参考此链接:-我应该使用乘法还是除法?