为什么浮点数除法比 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_t
和 uint16_t
首先提升为 int
,然后int
s 的划分发生了。 uint8_t
除法看起来比 int
快,因为它在转换为 int
时设置的位数更少,这导致除法完成得更快。
考虑以下 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_t
和 uint16_t
首先提升为 int
,然后int
s 的划分发生了。 uint8_t
除法看起来比 int
快,因为它在转换为 int
时设置的位数更少,这导致除法完成得更快。