打印

C6000点滴学习:c6000系列的C代码优化(二)

[复制链接]
435|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Roses|  楼主 | 2017-11-9 11:13 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
c6000系列的C代码优化(二)

二、双重循环和多重循环的优化总结  
        双重循环多重循环看起来比较复杂,但实际上多重循环优化方法比较简单,就在于一个字: “拆” ,一旦完成这一步之后,多重循环就成为单层循环,优化就可以按照普通的单层循环来做了。  多重循环的特点是在优化器优化时只在最内层循环中形成一个 pipeline,这样循环语句就不能充分利用 C6 的软件流水线,而且对于内部循环的次数较少的情况,消耗在 prolog 和eplog 上的 cycle 数也是不可忽视的。针对这种状况可以考虑将多重循环拆开形成一个单层循环,可以拆外层循环也可以拆内层循环,一般视具体情况而定。这样就可以充分利用优化器构成的 Pipeline。如下例:  
  •        void fir2(const short input[], const short coefs[], short out[])   
  •     {  
  •         int i, j;  
  •         int sum = 0;  
  •         for (i = 0; i < 40; i++)  
  •         {  
  •             for (j = 0; j < 16; j++)  
  •                      sum += coefs[j] * input[i + 15 - j];   
  •             out = (sum >> 15);  
  •     }  

复制代码
       内层循环循环次数较少,运算量也不大,资源方面只占用了一个乘法器,一个 cycle 只使用一次乘法器,而事实上我们可以在一个 cycle 内使用两个乘法器,所以还可以充分利用另外的一个乘法器。因此考虑将内层循环拆开来执行,如下:  
      
  • void fir2_u(const short input[], const short coefs[], short out[])   
  •     {  
  •     int i, j;  
  •     int sum;  
  •         for (i = 0; i < 40; i++)  
  •             {  
  •                   sum = coefs[0] * input[i + 15];   
  •           sum += coefs[1] * input[i + 14];  
  •           sum += coefs[2] * input[i + 13];  
  •           sum += coefs[3] * input[i + 12];  
  •           sum += coefs[4] * input[i + 11];  
  •           sum += coefs[5] * input[i + 10];  
  •           sum += coefs[6] * input[i + 9];  
  •           sum += coefs[7] * input[i + 8];  
  •           sum += coefs[8] * input[i + 7];  
  •           sum += coefs[9] * input[i + 6];  
  •                   sum += coefs[10] * input[i + 5];   
  •                   sum += coefs[11] * input[i + 4];   
  •                   sum += coefs[12] * input[i + 3];   
  •                   sum += coefs[13] * input[i + 2];   
  •                   sum += coefs[14] * input[i + 1];   
  •                   sum += coefs[15] * input[i + 0];   
  •           out = (sum >> 15);  
  •         }  

复制代码

         这样虽然代码长度增加了,可变成了单循环,所有的运算都参加到 pipeline 中来,在 Piped loop kernal 中产生每一个 cycle 内都使用了两个乘法器,充分利用了 DSP 内部的资源,提高了运行效率。又如下例:  
  • tot = 4;   
  • for (k = 0; k < 4; k++)   
  •      {  
  •         max = 0;  
  •           for (i = k; i < 44; i += STEP)   
  •         {  
  •             s = 0;  
  •                   for (j = i; j < 44; j++)   
  •             s = L_mac(s, x[j], h[j - i]);  
  •             y32 = s;  
  •             s = L_abs(s);  
  •             if (L_sub(s, max) > (Word32) 0)  
  •             max = s;  
  •         }  
  •         tot = L_add(tot, L_shr(max, 1));  
  •     }  

复制代码

        这个多层循环中一共有三层循环, 而最内层的循环的运算量很小, 只有一次乘累加操作,而我们知道 C6 中一个 packet中可以做两个乘累加运算,所以为了增加内部循环的运算,减少外部循环的层数,我们可以将第一层循环的操作拆开,其负责的运算加入到内部循环中,也就是在内层循环中一次做四次的乘累加运算,这样将多次操作形成 pipeline,提高了运行效率,优化后的 C代码如下:   
  •    tot = 4;  
  •      max0=0;  
  •      max1=0;  
  •      max2=0;  
  •      max3=0;  
  •     for (i = 0; i <44; i += STEP)                 //STEP=4,  11 times cirs  
  •      {  
  •                        //code  
  •          for (j=0;j<=40-i;j++)  
  •          {
  • s0=(Word32)(_sadd(s0,_smpy(hh[j],xx[j+i])));  
  •           s1=(Word32)(_sadd(s1,_smpy(hh[j],xx[j+i+1])));  
  •           s2=(Word32)(_sadd(s2,_smpy(hh[j],xx[j+i+2])));  
  •           s3=(Word32)(_sadd(s3,_smpy(hh[j],xx[j+i+3])));  
  •           }  
  •      }  
  •                 //code  

复制代码








相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

709

主题

1023

帖子

7

粉丝