Blackfin DSP的C语言优化之Circular Buffer

Blackfin提供了一组数据访问寄存器(DAG)用于提高对数据的访问效率,其中Circular Buffer是其一大特色。在汇编中,我们可以对它轻易地控制,但是在C语言下,并无法显式地使用它们。尽管如此,还是可以通过一些内建函数与编译选项提高数据的访问效率。

       Circular Buffer,即循环缓存,也就是指规定一段内存,假设起始地址为B,终止地址为B + L,当指针I大于B+L时,将自动将I调整为B + I % L

       先看以下这个例子:


1       for  (i  = 0 ; i  <   1000 ; i  +=  n)
2      {
3          b[i  %   80 =  i;
4      }
5 

一般的CPU都没有硬件支持%操作,它实际上是用子程序完成的,效率上非常低。而Blackfin DSP提供的DAG通过合理设计,可以实现%操作。

为了加深一下理解,这里贴出一个手写的汇编例子及其对应的C代码:

  

 

.import  " stdio.h " ;
.section L1_data ;
.byte  str [] =  ' the number:%d ' , 10 ;
.section program ;
.align  8 ;
.global _main ;

_main:
    link 
12 ;
    p0 =  0 ;
    b0 = p0 ;
    p1 =  9 ;     
    l1 =  4 ;
    i1 =  0 ;
    m1 =  1 ;
    lsetup(_main.l1, _main.l1.end) lc0 = p1 ;
_main. l1:
    i1 += m1
;
_main.l1. end:
    r1 = i1
;
    r0.l = lo( str ) ;
    r0.h = hi( str ) ;     
     call  _printf ;
    unlink ;
    RTS ;
_main. end:

  对应的C代码:

#include  < stdio.h >
int  main( void )
{
    
int  x  =   0 ;
    
int  i;

    
for  (i  =   0 ; i  <   9 ;i ++ )
        x 
=  (x  +   1 %   4 ;
    printf(
" the number:%d\n " , x);
    
return   0 ;
}

  输出结果:

the number: 1

好的,接下来我们谈谈如何在C语言中优化。

一种方法在编译时指定-force-circbuf选项,强制将所有循环索引和指针都用DAG实现,使用这种方法,程序员应该自己保证索引和指针总是在循环缓存范围内(即I应该总能在BL之间)。

Visual DSP++的该选项位置:


 

另一种方法,也是推荐的方法,是使用内建函数指导编译器优化。Blackfin提供了两个函数,它们的头文件是ccblkfn.h

循环索引:

 

long  circindex( long  index,  long  incr, unsigned  long  nitems);

  循环指针:

void   * circptr( void   * ptr,  long  incr,  void   * base , unsigned  long  buflen);

首先看循环索引的例子,及其反汇编代码来说明如何优化:


 

#include  < ccblkfn.h >
#include 
< stdio.h >
int  b[ 1000 ];
int  sum;

int  main(  void  )
{
    
int  i, j, n  =   20 ;

    
for  (i  =   0 ;i  <   1000 ; i  +=  n)
    {
        sum 
+=  (i  %   80 );
    }    
    
    
for  (i  =   0 , j  =   0 ; i  <   1000 ; i  +=   20 )
    {
        sum 
+=  j;
        j 
=  __builtin_circindex(j,  20 80 );
    }
    
return   0 ;
}



 

图中两个标注的地方分别是两个for语句内代码的反汇编,可以看出,第一个编译器并无优化,里面还用CALL调用了子函数。相比之下,第二个for每次循环只有2周期,效率相差至少5倍。

再看另一个有关循环指针的例子:

 

#include  < ccblkfn.h >
#include 
< stdio.h >
int  b[ 1000 ];
int  sum;

int  main(  void  )
{
    
int  i, j, n  =   20 ;
    
int   * p;
    
    
for  (i  = 0 ; i  <   1000 ; i  +=  n)
    {
        b[i 
%   80 =  i;
    }
    p 
=  b;
    
for  (i  =   0 ; i  <   1000 ; i  +=  n)
    {
        
* =  i;
        p 
=  __builtin_circptr(p, n ,b,  80 );
    }
    
    
return   0 ;
}


 

   从截图看到,两个for反汇编后的代码是一样的,说明编译器认为第一个for是可以安全优化的。

结语:尽管编译器可以自动对代码优化,但是并不是所有可以优化的地方都能检测出来,因此,有觉得有必要优化的地方,使用内建函数对编译器指导指导还是必要的。建议不使用-force-circbuf,在较大项目里,它使调试变得更困难。


 

转载于:https://www.cnblogs.com/pheye/archive/2010/11/29/1891498.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值