考虑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核心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指令/ intrinsincs可用于轻松地将float
计算的速度提高四倍。
例如,如果你看看用于Skylake的Agner Fog's instruction tables,32位整数除法的延迟是26个CPU周期,而SSE标量浮点除法的延迟是11个CPU周期(并且,令人惊讶的是,它需要相同的时间到划分四个包装的浮子)。
还要注意,在C和C ++中,没有对int
更短的数字进行划分,因此uint8_t
和uint16_t
首先被提升为int
然后int
s的划分发生。 uint8_t
除法看起来比int
更快,因为它在转换为int
时设置的位数更少,这使得除法更快完成。