代码优化-删除分支(实例1)

代码优化-删除分支(实例1)

 

分支是什么,具体可以参见:http://blog.csdn.net/housisong/archive/2007/10/05/1812117.aspx

这里举一个实际的例子来说明如何删除分支。

代码如下:

 

 1 #define  DIVIDE_BY(a,b) ((a < b)? (a = 0):(a /= b))
 2
 3 short  CXpegDCT::Quant( long  val, long  div)
 4
 5 {
 6
 7         if (val < 0{
 8
 9                   val = -val + (div>>1);/**//* for rounding */
10
11                   DIVIDE_BY(val, div);
12
13                   val = -val;
14
15         }
 else {
16
17                   val += div>>1/**//* for rounding */
18
19                   DIVIDE_BY(val, div);
20
21         }

22
23         return (short)val;
24
25}

26
27


上面的代码有两个分支;一个是用来判断val的值是否大于0,另外一个是判断val是否比被除数小。

 

对于第一个判断的目的就是要在val小于0的时候将其转换为正值,然后进行除法运算,最终还要将符号取反。因此对于val为正和负的不同在于运算前后的符号取反。

为了消除这个分支需要定义一个数组,这个数组包含两个元素;一个元素保存正val的绝对值,另外一个保存绝对值的负值,修改后的代码如下:

 

 1 Long m_TmpVals[ 2 ];
 2
 3 short  CXpegDCT::Quant( long  val, long  div)
 4
 5 {
 6
 7         long lTmpVal;
 8
 9         m_TmpVals[0= val;
10
11         m_TmpVals[1= -val;
12
13         lTmpVal = m_TmpVals[val<0];
14
15 
16
17         lTmpVal += (div>>1);/**//* for rounding */
18
19         DIVIDE_BY(lTmpVal, div);
20
21         m_TmpVals[0= lTmpVal;
22
23         m_TmpVals[1= -lTmpVal;
24
25         return (short)m_TmpVals[val<0];
26
27}

28

 

 

先要定义一个数组,然后在开始的时候给这个数组赋值,进行除法以后,同样将结果赋值数组,在对数组取值的时候使用val<0作为索引来查找。上面的程序与前面的程序是等价的。但它却消除了分支,从而让CPU能更好的预测。

 

其实对于除法的也是一个分支,在开始的时候我试图也消除这个分支,但结果事与愿为,我的转换确实消除了分支,带来的确实无能如何都要执行一次整数除法。例如:

 

Long m_TmpVals[ 2 ];

Long m_TmpVals2[
2 ];

short  CXpegDCT::Quant( long  val, long  div)

{

         
long lTmpVal;

         m_TmpVals[
0= val;

         m_TmpVals[
1= -val;

         lTmpVal 
= m_TmpVals[val<0];

 

         lTmpVal 
+= (div>>1);/**//* for rounding */

         m_TmpVals2[
1= 0;

         m_TmpVals2[
0= lTmpVal/div;

         m_TmpVals[
0= m_TmpVals2[lTmpVal<div];

         m_TmpVals[
1= - m_TmpVals2[lTmpVal<div];

         
return (short)m_TmpVals[val<0];

}

如上面的代码,虽然删除了分支,但却带来了一个必须的除法运算,所以这个分出删除未必是合适的。

你可能感兴趣的:(代码优化-删除分支(实例1))