高频率调用的函数一定要保证最优化,慎用除法和余数

转自: http://blog.csdn.net/mustanglau/article/details/4767937

在近期优化系统的过程中,发现有个函数在高压力下,竟然占用13.3%的时间,这个函数内部很简单,基本就是这样:

id_to_type(id)

{

      int iIndex = id0000;

      return g_data[iIndex].cType;

}

核心基本上就在这个%取余上,这往往使我们分组提高效率的常用方法,但是对于高频率调用上,则可以避免了。

如何解决呢?下面的附录说明了一些替代方法,但是显然并不是符合我们现在要解决的这个问题,当前我采用了修改设计的方法,将type合入到id的一 部分钟,必须 id 0x10000000 表示type=0的非等最大值,0x20000000表示type=1的非等最大值。

 

=============附录============

 

(说明:文章中的很多数据可能在新的CPU或不同的CPU或不同的系统环境下有不同的结果,可能不能面面俱到)
x86系列的CPU对于位运 算、加、减等基本指令都能在1个CPU周期内完成(现在的CPU还能乱序执行,从而使指令的平均CPU周期更小);现在的CPU,做乘法也是很快的(1个 CPU周期左右,或者是需要两/三个周期,但每个周期能启动一个新的乘指令),但作为基本指令的除法却超出很多人的预料,它是一条很慢的操作,整数和浮点 的除法都慢;我测试的英特尔P5赛扬CPU浮点数的除法差不多是37个CPU周期,整数的除法是80个CPU周期,AMD2200+浮点数的除法差不多是 21个CPU周期,整数的除法是40个CPU周期。(改变FPU运算精度对于除法无效)(SSE指令集的低路单精度数除法指令DIVPS 18个CPU周期,四路单精度数除法指令DIVSS 36个CPU周期) (x86求余运算和除法运算是用同一条CPU指令实现的;据说,很多CPU的整数除法都是用数学协处理器的浮点除法器完成的;有一个推论就是,浮点除法和 整数除法不能并行执行)
  本文将给出一些除法的优化方法或替代算法  (警告:某些替代算法并不能保证完全等价!)
  1.尽量少用除法
   比如: if (x/y>z) ...
   改成: if ( ((y>0)&&(x>y*z))||((y<0)&&(x
   (少用求余)
   比如: ++index; if (index>=count) index=index % count;  //assert(index
   改成: ++index; if (index>=count) index=index - count;
  2.用减法代替除法
   如果知道被除数是除数的很小的倍数,那么可以用减法来代替除法
   比如:  uint32 x=200;
         uint32 y=70;
           uint32 z=x/y;
   改成:  uint z=0;
           while (x>=y)
           {
              x-=y;  ++z;
           }
   一个用减法和移位完成的除法 (如果你没有除法指令可用:)
     uint32 div(uint64 s,uint32 z) //return u/z  
     {
         uint32 x=(uint32)(s>>32);
         uint32 y=(uint32)s;
         //y保存商 x保存余数
         for (int i=0;i<32;++i)
         {
             uint32 t=((int32)x) >> 31;
             x=(x<<1)|(y>>31);
             y=y<<1;
             if ((x|t)>=z)
             {
                 x-=z;
                 ++y;
             }
         }
    

你可能感兴趣的:(高频率调用的函数一定要保证最优化,慎用除法和余数)