关于嵌入式性能调优

  本来对嵌入式性能调优方面的一些文章还有些不以为然,但经过自己亲身体验之后,我不得不承认那些都是无比正确的。
  对于性能问题,我一向的观点是,首先优化算法,能够查表的情况下就查表(如三角函数),能展开写的就不循环甚至递归。然后是尽量少的拷贝和分配内存,数据能共享的就共享,能一次分配的内存就一次分配。最后才是代码细节的优化。代码细节的优化大概有以下几点:
  1、能预先算好的就预先算好。比如旋转变换的sin(angle)和cos(angle)就可以预先算好,而不必每个点都重新算一遍。
  2、干掉所有浮点运算。当然,这是不可能的,我们只能做到在最花CPU时间的地方见不到浮点运算,这往往要结合第一点来实现,我们可以预先算好需要的参数,假如它是浮点数,那么我们可以将其乘以2^n,这个n取决于需要的精度,然后取整。在每个需要乘以这个参数的地方加上>>n。
  3、干掉所有除法。我们往往可以将其转化为浮点乘法,然后应用第二点。
  4、在可能的情况下,用移位代替乘除法。
  5、赋值、比较等时候,数据类型要相符,再不济也要加上强制类型转换。
  6、多用宏函数或内联函数。
  下面是一些高效的算法:
一、平方根
  1. /* fsqrt.c
  2.  *
  3.  * A fast square root program adapted from the code of
  4.  * Paul Lalonde and Robert Dawson in Graphics Gems I.
  5.  * The format of IEEE double precision floating point numbers is:
  6.  *
  7.  * SEEEEEEEEEEEMMMM MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM
  8.  *
  9.  * S = Sign bit for whole number
  10.  * E = Exponent bit (exponent in excess 1023 form)
  11.  * M = Mantissa bit
  12.  */
  13. #include <stdio.h>
  14. #include <math.h>
  15. /* MOST_SIG_OFFSET gives the (int *) offset from the address of the double
  16.  * to the part of the number containing the sign and exponent.
  17.  * You will need to find the relevant offset for your architecture.
  18.  */
  19. #define MOST_SIG_OFFSET 1
  20. /* SQRT_TAB_SIZE - the size of the lookup table - must be a power of four.
  21.  */
  22. #define SQRT_TAB_SIZE 16384
  23. /* MANT_SHIFTS is the number of shifts to move mantissa into position.
  24.  * If you quadruple the table size subtract two from this constant,
  25.  * if you quarter the table size then add two.
  26.  * Valid values are: (16384, 7) (4096, 9) (1024, 11) (256, 13)
  27.  */
  28. #define MANT_SHIFTS   7
  29. #define EXP_BIAS   1023       /* Exponents are always positive     */
  30. #define EXP_SHIFTS 20         /* Shifs exponent to least sig. bits */
  31. #define EXP_LSB    0x00100000 /* 1 << EXP_SHIFTS                   */
  32. #define MANT_MASK  0x000FFFFF /* Mask to extract mantissa          */
  33. int        sqrt_tab[SQRT_TAB_SIZE];
  34. void
  35. init_sqrt_tab()
  36. {
  37.         int           i;
  38.         double        f;
  39.         unsigned int  *fi = (unsigned int *) &f + MOST_SIG_OFFSET;
  40.         
  41.         for (i = 0; i < SQRT_TAB_SIZE/2; i++)
  42.         {
  43.                 f = 0; /* Clears least sig part */
  44.                 *fi = (i << MANT_SHIFTS) | (EXP_BIAS << EXP_SHIFTS);
  45.                 f = sqrt(f);
  46.                 sqrt_tab[i] = *fi & MANT_MASK;
  47.                 f = 0; /* Clears least sig part */
  48.                 *fi = (i << MANT_SHIFTS) | ((EXP_BIAS + 1) << EXP_SHIFTS);
  49.                 f = sqrt(f);
  50.                 sqrt_tab[i + SQRT_TAB_SIZE/2] = *fi & MANT_MASK;
  51.         }
  52. }
  53. double
  54. fsqrt(f)
  55. double f;
  56. {
  57.         unsigned int e;
  58.         unsigned int   *fi = (unsigned int *) &f + MOST_SIG_OFFSET;
  59.         if (f == 0.0) return(0.0);
  60.         e = (*fi >> EXP_SHIFTS) - EXP_BIAS;
  61.         *fi &= MANT_MASK;
  62.         if (e & 1)
  63.                 *fi |= EXP_LSB;
  64.         e >>= 1;
  65.         *fi = (sqrt_tab[*fi >> MANT_SHIFTS]) |
  66.               ((e + EXP_BIAS) << EXP_SHIFTS);
  67.         return(f);
  68. }
  69. void
  70. dump_sqrt_tab()
  71. {
  72.         int        i, nl = 0;
  73.         printf("unsigned int sqrt_tab[] = {/n");
  74.         for (i = 0; i < SQRT_TAB_SIZE-1; i++)
  75.         {
  76.                 printf("0x%x,", sqrt_tab[i]);
  77.                 nl++;
  78.                 if (nl > 8) { nl = 0; putchar('/n'); }
  79.         }
  80.         printf("0x%x/n", sqrt_tab[SQRT_TAB_SIZE-1]);
  81.         printf("};/n");
  82. }
二、距离计算
  1. //
  2. // 这个函数计算从(0,0)到(x,y)的距离,相对误差为3.5%
  3. //
  4. int FastDistance2D(int x, int y)
  5. {
  6.     x = abs(x);
  7.     y = abs(y);
  8.     int mn = MIN(x,y);
  9.     return(x+y-(mn>>1)-(mn>>2)+(mn>>4));
  10. }
  11. //
  12. // 该函数计算(0,0,0)到(x,y,z)的距离,相对误差为8%
  13. //
  14. float FastDistance3D(float fx, float fy, float fz)
  15. {
  16.     int temp;
  17.     int x,y,z;
  18.     // 确保所有的值为正
  19.     x = int(fabs(fx) * 1024);
  20.     y = int(fabs(fy) * 1024);
  21.     z = int(fabs(fz) * 1024);
  22.     // 排序
  23.     if (y < x) SWAP(x,y,temp)
  24.     if (z < y) SWAP(y,z,temp)
  25.     if (y < x) SWAP(x,y,temp)
  26.     int dist = (z + 11 * (y >> 5) + (x >> 2) );
  27.     return((float)(dist >> 10));
  28. }
三、随机数发生
  1. /*
  2. A 32 bit random number generator. An implementation in C of the algorithm given by
  3. Knuth, the art of computer programming, vol. 2, pp. 26-27. We use e=32, so 
  4. we have to evaluate y(n) = y(n - 24) + y(n - 55) mod 2^32, which is implicitly
  5. done by unsigned arithmetic.
  6. */
  7. unsigned int Random32(void) {
  8.   /*
  9.   random numbers from Mathematica 2.0.
  10.   SeedRandom = 1;
  11.   Table[Random[Integer, {0, 2^32 - 1}]
  12.   */
  13.   static const unsigned long x[55] = {
  14.     1410651636UL, 3012776752UL, 3497475623UL, 2892145026UL, 1571949714UL,
  15.     3253082284UL, 3489895018UL, 387949491UL, 2597396737UL, 1981903553UL,
  16.     3160251843UL, 129444464UL, 1851443344UL, 4156445905UL, 224604922UL,
  17.     1455067070UL, 3953493484UL, 1460937157UL, 2528362617UL, 317430674UL, 
  18.     3229354360UL, 117491133UL, 832845075UL, 1961600170UL, 1321557429UL,
  19.     747750121UL, 545747446UL, 810476036UL, 503334515UL, 4088144633UL,
  20.     2824216555UL, 3738252341UL, 3493754131UL, 3672533954UL, 29494241UL,
  21.     1180928407UL, 4213624418UL, 33062851UL, 3221315737UL, 1145213552UL,
  22.     2957984897UL, 4078668503UL, 2262661702UL, 65478801UL, 2527208841UL,
  23.     1960622036UL, 315685891UL, 1196037864UL, 804614524UL, 1421733266UL,
  24.     2017105031UL, 3882325900UL, 810735053UL, 384606609UL, 2393861397UL };
  25.   static int init = 1;
  26.   static unsigned long y[55];
  27.   static int j, k;
  28.   unsigned long ul;
  29.   
  30.   if (init)
  31.   {
  32.     int i;
  33.     
  34.     init = 0;
  35.     for (i = 0; i < 55; i++) y[i] = x[i];
  36.     j = 24 - 1;
  37.     k = 55 - 1;
  38.   }
  39.   
  40.   ul = (y[k] += y[j]);
  41.   if (--j < 0) j = 55 - 1;
  42.   if (--k < 0) k = 55 - 1;
  43.   return((unsigned int)ul);
  44. }
四、FFT变换
  1. /*
  2. This computes an in-place complex-to-complex FFT
  3. x and y are the real and imaginary arrays of n=2^m points. 
  4. o(n)=n*log2(n) 
  5. dir =  1 gives forward transform 
  6. dir = -1 gives reverse transform  
  7. FFT algorithm by Cooley and Tukey, 1965
  8. */
  9. bool _stdcall FFT(int dir,int m,double *x,double *y)
  10. {
  11.     long nn,i,i1,j,k,i2,l,l1,l2; 
  12.     double c1,c2,tx,ty,t1,t2,u1,u2,z; 
  13.     
  14.     /* Calculate the number of points */
  15.     nn = 1<<m; 
  16.     
  17.     /* Do the bit reversal */ 
  18.     i2 = nn >> 1; 
  19.     j = 0; 
  20.     for (i=0;i<nn-1;i++) { 
  21.         if (i < j) { 
  22.             tx = x[i]; 
  23.             ty = y[i]; 
  24.             x[i] = x[j]; 
  25.             y[i] = y[j]; 
  26.             x[j] = tx; 
  27.             y[j] = ty; 
  28.         } 
  29.         k = i2; 
  30.         while (k <= j) { 
  31.             j -= k; 
  32.             k >>= 1; 
  33.         } 
  34.         j += k; 
  35.     } 
  36.     
  37.     /* Compute the FFT */ 
  38.     c1 = -1.0; 
  39.     c2 = 0.0; 
  40.     l2 = 1; 
  41.     for (l=0;l<m;l++) { 
  42.         l1 = l2; 
  43.         l2 <<= 1; 
  44.         u1 = 1.0; 
  45.         u2 = 0.0; 
  46.         for (j=0;j<l1;j++) { 
  47.             for (i=j;i<nn;i+=l2) { 
  48.                 i1 = i + l1; 
  49.                 t1 = u1 * x[i1] - u2 * y[i1]; 
  50.                 t2 = u1 * y[i1] + u2 * x[i1]; 
  51.                 x[i1] = x[i] - t1; 
  52.                 y[i1] = y[i] - t2; 
  53.                 x[i] += t1; 
  54.                 y[i] += t2; 
  55.             } 
  56.             z =  u1 * c1 - u2 * c2; 
  57.             u2 = u1 * c2 + u2 * c1; 
  58.             u1 = z; 
  59.         } 
  60.         c2 = sqrt((1.0 - c1) / 2.0); 
  61.         if (dir == 1) 
  62.             c2 = -c2; 
  63.         c1 = sqrt((1.0 + c1) / 2.0); 
  64.     } 
  65.     
  66.     /* Scaling for forward transform */ 
  67.     if (dir == 1) { 
  68.         for (i=0;i<nn;i++) { 
  69.             x[i] /= (double)nn; 
  70.             y[i] /= (double)nn; 
  71.         }
  72.     } 
  73.     
  74.     return true
  75. }
  最后,不得不提:STL真的很低效。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值