为什么在添加之前将 float 转换为 int?
Why is a float being converted to an int before adding?
当我观察到一些奇怪的东西时,我在 https://gcc.godbolt.org/ 上闲逛。考虑以下函数:
#include <algorithm>
#include <cstdlib>
#include <functional>
float dot(float src1[], float src2[], int size) {
float* vecmul = static_cast<float*>(malloc(size * sizeof (float)));
float dotprod = 0;
std::transform(src1, src1+size, src2, vecmul, std::multiplies<float>());
dotprod = std::accumulate(vecmul, vecmul+size, 0);
free(vecmul);
return dotprod;
}
在 x86 gcc 4.9.2
上使用标志 -O3 -std=c++11
这将被编译为:
dot(float*, float*, int):
// load args, do multiplication from std::transform (with mulss)
.L22:
pxor %xmm0, %xmm0
addq , %rcx
cvtsi2ss %edx, %xmm0 *
addss -4(%rcx), %xmm0 *
cmpq %rcx, %rsi *
cvttss2si %xmm0, %edx *
jne .L22
pxor %xmm0, %xmm0
cvtsi2ss %edx, %xmm0
.L4:
// pop arguments, free, etc.
我很好奇为什么我们有浮点数到整数的转换,然后是整数加法,然后再转换回来(星号线)。为什么这会比直接 fadd
更快?
std::accumulate
的累加器类型由其第三个参数确定。 0
是一个 int
,所以 std::accumulate(vecmul, vecmul+size, 0);
会将每个中间相加的结果转换为 int
,最后 return 一个 int
.
您希望 std::accumulate(vecmul, vecmul+size, 0.0f);
使累加器成为 float
。
当我观察到一些奇怪的东西时,我在 https://gcc.godbolt.org/ 上闲逛。考虑以下函数:
#include <algorithm>
#include <cstdlib>
#include <functional>
float dot(float src1[], float src2[], int size) {
float* vecmul = static_cast<float*>(malloc(size * sizeof (float)));
float dotprod = 0;
std::transform(src1, src1+size, src2, vecmul, std::multiplies<float>());
dotprod = std::accumulate(vecmul, vecmul+size, 0);
free(vecmul);
return dotprod;
}
在 x86 gcc 4.9.2
上使用标志 -O3 -std=c++11
这将被编译为:
dot(float*, float*, int):
// load args, do multiplication from std::transform (with mulss)
.L22:
pxor %xmm0, %xmm0
addq , %rcx
cvtsi2ss %edx, %xmm0 *
addss -4(%rcx), %xmm0 *
cmpq %rcx, %rsi *
cvttss2si %xmm0, %edx *
jne .L22
pxor %xmm0, %xmm0
cvtsi2ss %edx, %xmm0
.L4:
// pop arguments, free, etc.
我很好奇为什么我们有浮点数到整数的转换,然后是整数加法,然后再转换回来(星号线)。为什么这会比直接 fadd
更快?
std::accumulate
的累加器类型由其第三个参数确定。 0
是一个 int
,所以 std::accumulate(vecmul, vecmul+size, 0);
会将每个中间相加的结果转换为 int
,最后 return 一个 int
.
您希望 std::accumulate(vecmul, vecmul+size, 0.0f);
使累加器成为 float
。