最近在做自己的玩具项目Physics2D的时候,对Vector2D是应该使用float还是double类型纠结了很久,通常来说(特别是在学校教学当中),大家都会直观的认为float精度输给double,但是速度会远胜于double,毕竟double比float位数长那么一大截,可实际上真的是这样么?昨天阅读了老赵的博客文章,正巧看到了一个不错的CodeTimer实现,空想没用,干脆用实际测试到的数据说话。

下表为微软给出的两个类型的表示范围以及精度,作为一个参考先放在这里:

Type Approximate range Precision
float ±1.5e−45 to ±3.4e38 7 digits
double ±5.0e−324 to ±1.7e308 15-16 digits

 

我编写了5组测试用例,分别对应加、减、乘、除以及混合的运算,代码如下所示:

 

测试框架如下,所有被执行的测试用例都提前进行了预热(想深入了解的可以阅读《CLR via C#》),从而确保所有的待测代码都已经被JIT编译成了本地代码:

中间的这行代码 CodeTimer.Initialize(); 的作用是让当前进程及线程的优先级设置为最高,从而尽量减少操作系统调度导致的性能差异,更多内容可以点上面老赵的博客链接查看。

测试的结果如下:

 

实话说,float与double在性能上的差异几乎可以忽略,而且在多次测试的时候发现,float与double其实互有胜负,也就是说你看到的差异很可能是误差所导致的。从结果来看,double在性能上并不输给float,然而double却能够提供比float高一倍之余的精度,而占用内存的代价在如今可以轻易堆高内存的时代来说,通常也是不值一提的。基于这个测试结果,我将我项目中所有用到float的地方都替换成了double,不仅能够提供更高精度的物理模拟效果,而且在应用某些数学运算的时候(如Math.Sin())可以避免类型转换。

至于为什么double和float的性能差不多,我也在Stackoverflow中找到了答案,在现代CPU架构中,有专门用于浮点运算的运算器(FPU),对于这个运算器来说,无论你是float还是double,其实运算的时候都是按它的最高支持位宽来运算的,所以float在运算的时候会先被转换为FPU支持的位宽才进行运算,因此在现代CPU中,float与double的运算性能几乎是不存在差异的。但是如果你的机器很老很老,或者你在为某些不具有FPU的老式嵌入式设备开发性能敏感的程序的时候,使用double的性能代价就会显现出来,在这种时候,如果你对精度的要求不高,那么就应该选择float。不过对于针对目前平台的项目而言,我自己是能用double,就不用float。

本文的测试框架已经发布在我的GitHub中:https://github.com/Blueve/DoubleVSFloatBenchmark


2015.10.12更新
最近查阅MSDN发现里面已经有一篇文章提及了这些基础运算的性能问题:Writing Faster Managed Code: Know What Things Cost
其中的表格

Table 2   Arithmetic Operation Times (ns)

Avg Min Primitive Avg Min Primitive
1.0 1.0 int add 1.3 1.3 float add
1.0 1.0 int sub 1.4 1.4 float sub
2.7 2.7 int mul 2.0 2.0 float mul
35.9 35.7 int div 27.7 27.6 float div
2.1 2.1 int shift
2.1 2.1 long add 1.5 1.5 double add
2.1 2.1 long sub 1.5 1.5 double sub
34.2 34.1 long mul 2.1 2.0 double mul
50.1 50.0 long div 27.7 27.6 double div
5.1 5.1 long shift

In the old days, floating-point math was perhaps an order of magnitude slower than integer math. As Table 2 shows, with modern pipelined floating-point units, it appears there is little or no difference. It is amazing to think an average notebook PC is a now gigaflop class machine (for problems that fit in cache).
Let’s take a look at a line of jitted code from the integer and floating point add tests:

希望了解更多内容的读者,可以通过连接查看更多内容


参考文献

  1. 一个简单的性能计数器:CodeTimer. http://blog.zhaojie.me/2009/03/codetimer.html
  2. Floating-Point Types Table (C# Reference). https://msdn.microsoft.com/en-US/library/9ahet949(v=vs.80).aspx
  3. Float vs Double Performance. http://stackoverflow.com/questions/417568/float-vs-double-performance

 

说点什么

您将是第一位评论人!

提醒
wpDiscuz