为什么浮点数除法比 C++ 中的整数除法快?

Why float division is faster than integer division in c++?

考虑以下 C++ 代码片段:(visual studio 2015)

第一块

const int size = 500000000;
int sum =0;
int *num1 = new int[size];//initialized between 1-250
int *num2 = new int[size];//initialized between 1-250
for (int i = 0; i < size; i++)
{
    sum +=(num1[i] / num2[i]);
}

第二块

const int size = 500000000;
int sum =0;
float *num1 = new float [size]; //initialized between 1-250 
float *num2 = new float [size]; //initialized between 1-250
for (int i = 0; i < size; i++)
{
    sum +=(num1[i] / num2[i]);
}

我预计第一个块运行得更快,因为它是整数运算。但是第二块要快得多,尽管它是浮点运算。这是我的基准测试结果: 分配:

Type    Time
uint8   879.5ms
uint16  885.284ms
int     982.195ms
float   654.654ms

以及浮点乘法比整数乘法快。 这是我的基准测试结果:

乘法:

Type    Time
uint8   166.339ms
uint16  524.045ms
int     432.041ms
float   402.109ms

我的系统规格:CPU core i7-7700 ,Ram 64GB,Visual studio 2015

由于 floating point number representation 中的指数部分,浮点数除法比整数除法更快。要将一个指数除以另一个指数,使用简单的减法。

int32_t 除法需要 31 位数字的快速除法,而 float 除法需要 24 位尾数的快速除法(尾数中的前导隐含而不存储在浮点数中数)和更快的 8 位指数减法。

看到 excellent detailed explanation how division is performed in CPU.

可能值得一提的是,SSE和AVX指令只提供浮点除法,不提供整数除法。 SSE instructions/intrinsincs 可用于轻松将 float 计算速度提高四倍。

如果你查看 Agner Fog's instruction tables,例如,对于 Skylake,32 位整数除法的延迟是 26 CPU 个周期,而 SSE 标量浮点除法的延迟是 11 CPU 个周期(而且,令人惊讶的是,划分四个打包浮点数需要相同的时间)。

另请注意,在 C 和 C++ 中,没有比 int 短的数字除法,因此 uint8_tuint16_t 首先提升为 int,然后ints 的划分发生了。 uint8_t 除法看起来比 int 快,因为它在转换为 int 时设置的位数更少,这导致除法完成得更快。