效率 - c++中float的计算速度比double慢?

浏览:29日期:2023-05-29

问题描述

c++中float的计算速度比double慢

 浮点运算都是以双精度进行的,即使只有float的运算,也要先转换成double型再计算。所以doublex型比float型要快一点。C++ 标准要求 float 类型至少要能精确表示到小数点后6位,并且整数部分的表示范围至少要达到 1.0-37 -- 10+37 。float 一般是 32 位的。C ++标准规定double 类型的整数部分的最小表示范围和 float 一样,都是 1.0E-37 到 1.0E+37,但是它要求 double 类型的小数部分至少要能精确到小数点后 10 位。double 通常是 64 位的。

VC编译的时候float会转double,建议以后直接用double做浮点数运算,这样既能保证精度有能提高速度。这是在网上找到的一段回答。 但在没有指定编译环境和语言时,很多网上的帖子都直接说float比较快。 所以现在我乱了。

问题解答

回答1:

VC++来说,一般分为两种情况。

第一种情况是你编译32位程序的时候,它会使用X87指令集。在现代的cpu里面,X87内部有一个小堆栈,每一个元素都是80位或者128位的浮点。不管你用的是float、double,还是其他的类型,反正push进去了都会normalize成一样长的80位或者128位的浮点,全部算完了再给你转回来。所以速度应该是几乎一致的。

第二种情况是你编译64位程序,或者打开了MMX、SSE、AVX指令集优化,或者你干脆就是用intrinsic来直接使用这些指令集。这些指令目前支持float和double,而且不会跟X87一样统一转格式。double不仅数据是float的两倍,而且同样大小的寄存器可以同时存放的double数量要比float数量少一半,因此并行之后,float就会比double快很多。

当然了,在很多情况下,float的精度实际上是不够的,而且使用intrinsic的时候,你自己的水平的影响比double的影响要大几个数量级,所以看你的需要了,以需求为主。

回答2:

是double快点的。我写了个测试代码`main(){//float f1=0.0;double f1=0.0;int i,j;for(i=0;i<100000;i++){for(j=0;j<10000;j++)f1+=1.1;f1-=11000;}printf('%fn',f1);}`float:root@i5a:~/test# time ./a.out-1412.595703

real 0m3.063suser 0m3.065ssys 0m0.000s

doubuletime ./a.out0.000204

real 0m0.843suser 0m0.840ssys 0m0.004s

相差近4倍来看看gcc -c -S,只看循环体部分double:

.L2:movl $10000, %eax.p2align 4,,10.p2align 3.L5:subl $1, %eaxaddsd %xmm1, %xmm0jne .L5subl $1, %edxsubsd %xmm2, %xmm0jne .L2

再来看看float:

.L2:movl $10000, %eax.p2align 4,,10.p2align 3.L5:unpcklps%xmm0, %xmm0subl $1, %eaxcvtps2pd%xmm0, %xmm0addsd %xmm1, %xmm0unpcklpd%xmm0, %xmm0cvtpd2ps%xmm0, %xmm0jne .L5subl $1, %edxsubss %xmm2, %xmm0jne .L2unpcklps%xmm0, %xmm0movl $.LC3, %edimovl $1, %eaxcvtps2pd%xmm0, %xmm0jmp printf

都已经开启了-O2优化。

再来看看编译成32位的情况。double:.L8:

fxch %st(1)

.L2:

movl $10000, %eax .p2align 4,,7 .p2align 3

.L5:

subl $1, %eax fadd %st, %st(1) jne .L5 fxch %st(1) subl $1, %edx fsubs .LC2 jne .L8

float:.L9:

fxch %st(1)

.L2:

movl $10000, %eax jmp .L5 .p2align 4,,7 .p2align 3

.L8:

fxch %st(1)

.L5:

fadd %st, %st(1) fxch %st(1) subl $1, %eax fstps 12(%esp) flds 12(%esp) jne .L8 subl $1, %edx fsubs .LC2 jne .L9

测试结果double跟64位差不多,0.85秒,float2.78秒,比64位的float要快一点点。

相关文章: