DSP 优化心得解析_第1页
DSP 优化心得解析_第2页
已阅读5页,还剩27页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、C6XX优化经验总结优化经验总结一、一、c6xc6x 的编译的常用选项的编译的常用选项(一)c6x的编译程序为cl6x.exe”使用的方法CI6xoptionsfilenamesCI6x:编译程序Options:编译选项Filenames:C或汇编源文件说明:编译选项是一个字母或者两个字母,对大小写不敏感。编译选项的前面需要有一个一”符号。一个字母的选项可以合并在一起。比如一 sgq”与一sgq”相同。两个字母的选项如果第一个字母相同也可以合并在一起。 比如一mgt”与一mgmt相同。(二)有关优化的选项-mt:表示在程序中没有使用alaising技术,这使得编译器可以进行比较好的优化。-03

2、:对文件级别进行最强的优化,一般在编译时应该使用这个选项。但是在个别情况下使用这个选项优化程序可能会出现错误(-o2有相同现象,-o0和-o1不会出现错误)。可能是在优化循环,组织流水线的时候发生错误。如果有这种现象出现可以同时使用-g选项,程序优化就不会出现错误,但是优化效果会下降。另外可以调整程序的表达方式,可能会避免编译器发生错误。-pm:在程序级别进行优化。可以将所以文件联合在一起进行优化,主要有去掉没有被调用的函数、总是常数的变量以及没有使用的函数返回值。 建议由程序员自己进行这种优化工作。 使用这个选项在win98下编译可能会出现找不到编译程序的情况。-msO:不使用冗余循环进行优

3、化,减小程序的大小。一般情况下这个选项对程序大小的优化作用不明显。-mhn:去掉流水线的epilog,减小程序的大小。这个选项的作用比较明显。但是有可能出现读取地址超出有效范围的问题,所以要在数据段的开始和结尾处增加一些pading,或者在分配内存时保证数组的前面和后面一段范围内都是有效的地址。可选的参数n给出这种pading的长度字节数。(三)保留编译和优化信息的选项-k:保留优化后生成汇编语言文件。-s:汇编语言文件中加入优化信息,如果没有则加入C语言源程序作为注释。-mw:在汇编语言文件加入软件流水线信息。(四)有关调试和剖析的选项-g:允许符号调试,在“out”文件中包含符号信息和行号

4、信息,可以在c语言级别进行调试和剖析。使用联合使用一g、一mt和一o3可以保证能够进行符号调试的情况下最大限度的优化。-mg:允许profile优化后的程序。在“out”文件中包含符号信息和很少的行号信息。允许在c语言的函数基本进行剖析。如果联合使用这两个选项,一g选项可能被忽略,结果与只用一mg相同。(五)其它类型-mln:生成大内存模式的程序。一mIO:缺省情况下将集合变量(数组和结构)作为far型。-ml1:缺省情况下将全部函数作为far型-ml2:等于-ml0加-ml1-ml3:缺省情况下将全部数据和函数作为far型(六)建议使用的编译方式CI6xgkmto3mwss“filename

5、方式1用于程序的调试,这种方式具有比较强的优化能力,并且支持符号调试。在编译的过程中不会发生错误。由于生成的“out”文件中包含了符号信息和行号信息,所以比较大。CI6xkmgt03mwss“filename方式2用于程序的剖析(profile),这种方式的优化能力几乎最强(绝大多数情况下与方式3相同),并且支持对程序进行profile。文件中只包含了符号信息和很少的行号信息,所以“out”文件比较小。CI6xkmto3mwss“filename方式3用于最终的发行版本程序, 可以对程序进行最强的优化, 并且去掉了全部的符号和行号信息,所以“out文件比较小。由多个文件组成的程序应该编写mak

6、efile,将编译参数放在该文件中,并在其中说明使用的编译器的版本号。(七)连接参数heap:指定堆的大小stack:指定栈的大小连接的各种选项应该统一放在“cmd”文件中二、双重循环和多重循环的优化总结双重循环多重循环看起来比较复杂,但实际上多重循环优化方法比较简单,就在于一个字:拆,一旦完成这一步之后,多重循环就成为单层循环,优化就可以按照普通的单层循环来做了。多重循环的特点是在优化器优化时只在最内层循环中形成一个pipeline,这样循环语句就不能充分利用C6的软件流水线,而且对于内部循环的次数较少的情况,消耗在prolog和eplog上的cycle数也是不可忽视的。针对这种状况可以考虑

7、将多重循环拆开形成一个单层循环,可以拆外层循环也可以拆内层循环,一般视具体情况而定。这样就可以充分利用优化器构成的Pipeline。如下例:voidfir2(constshortinput,constshortcoefs,shortout)inti,j;intsum=0;for(i=0;i40;i+)for(j=0;j15);内层循环循环次数较少,运算量也不大,资源方面只占用了一个乘法器,一个cycle只使用一次乘法器,而事实上我们可以在一个cycle内使用两个乘法器, 所以还可以充分利用另外的一个乘法器。因此考虑将内层循环拆开来执行,如下:voidfir2_u(constshortinput

8、,constshortcoefs,shortout)inti,j;intsum;for(i=0;i15);这样虽然代码长度增加了,可变成了单循环,所有的运算都参加到pipeline中来,在Pipedloopkernal中产生每一个cycle内都使用了两个乘法器, 充分利用了DSP内部的资源, 提高了运行效率。又如下例:tot=4;for(k=0;k4;k+)max=0;for(i=k;i44;i+=STEP)s=0;for(j=i;j(Word32)0)max=s;tot=L_add(tot,L_shr(max,1);在这个多层循环中一共有三层循环,而最内层的循环的运算量很小,只有一次乘累加操

9、作,而我们知道C6中一个packet中可以做两个乘累加运算,所以为了增加内部循环的运算,减少外部循环的层数,我们可以将第一层循环的操作拆开,其负责的运算加入到内部循环中,也就是在内层循环中一次做四次的乘累加运算,这样将多次操作形成pipeline,提高了运行效率,优化后的C代码如下:tot=4;max0=0;max1=0;max2=0;max3=0;for(i=0;i16*/aReg=(aReg/65536);aReg=floor(aReg);/*(unsigned)low1*(signed)high2*/aReg+=(double)(Oxffff&L_var1)*(double)L_

10、shr(L_var2,16)*2.0;/*(unsigned)low2*(signed)high1*/aReg+=(double)(Oxffff&L_var2)*(double)L_shr(L_var1,16)*2.0;/*16*/aReg=(aReg/65536);aReg=floor(aReg);/*(signed)high1*(signed)high2*/aReg+=(double)(L_shr(L_var1,16)*(double)(L_shr(L_var2,16)*2.0;/*saturateresult.*/lvar=L_saturate(aReg);return(Ivar

11、);2、改编后的代码:staticinlineWord32L_mpy_ll(Word32L_var1,Word32L_var2)Word32aReg_hh;Word40aReg,aReg,aReg_lh,aReg_hl;aReg_ll=(Word40)_mpyu(L_va门,L_var2)16;aRegh=(Word40)_mpyluhs(L_var1,L_var2);aReg_hl=(Word40)_mpyhslu(L_var1,L_var2);aReg_hh=_smpyh(L_va门,L_var2);aReg=_lsadd(aRegi_ll,sadd(aRegh,aReg_hl);aReg

12、=sadd(aReg15,aReg_hh);return(_sat(aReg);3、优化方法说明:C6000编译器提供的intrinsic可快速优化C代码,intrinsic用前下划线表示同调用函数一样可以调用它,即直接内联为C6000的函数。例如,在上例的源代码中没有使用intrinsics,每一行C代码需多个指令周期,在改编后的代码中,每一行代码仅需一个指令周期。例如,“aRegil=(Word40)_mpyu(L_var1,L_var2)16”中“_mpy就是一个intrinsics函数,它表示两个无符号数的高16位相乘,结果返回。C6000支持的所有intrinsics指令及其功能参见

13、TMS320C6000系列DSP的原理与应用一书的第265、266页,该书还提供了另外的例子。这些内联函数定义在CCS所在的C6000/CGTOOLS/Include目录下的C6X.h文件中。下面这个例子是C6000的“ProgrammersGuide”上提取的使用intrinsics优化C代码的例子。源代码:intdotprod(constshort*a,constshort*b,unsignedintN)inti,sum=0;for(i=0;iN;i+)sum+=ai*bi;returnsum;改编后代码:intdotprod(constint*a,constint*b,unsignedi

14、ntN)inti,sum1=0,sum2=0;for(i=0;i1);i+)sum1+=_mpy(ai,bi);sum2+=_mpyh(ai,bi);returnsum1+sum2;技巧:在C语言的调试全部通过以后,可以尝试将尽可能多的语句使用intrinsics函数加以改编,尤其在循环体内,这种改编可以大幅度减少执行时间。四、1、源代码:voidfir_fxd1(shortinput,shortcoefs,shortout)inti,j;for(i=0;i40;i+)for(j=0;j16;j+)outi*16+j=coefsj*inputi+15-j;2、改编后的代码:voidfir_fx

15、d2(constshortinput,constshortcoefs,shortout)inti,j;for(i=0;i40;i+)for(j=0;j16;j+)outi*16+j=coefsj*inputi+15-j;3、优化方法说明:C6000编译器如果确定两条指令是不相关的, 则安排它们并行执行。 关键字const可以指定一个变量或者一个变量的存储单元保持不变。这有助于帮助编译器确定指令的不相关性。例如上例中,源代码不能并行执行,而结果改编后的代码可以并行执行。4、技巧:使用const可以限定目标,确定存在于循环迭代中的存储器的不相关性。五、1、源代码:voidvecsum(short*

16、sum,short*in1,short*in2,unsignedintN)inti;for(i=0;i2;_nassert(N=20);for(i=0;isz;i+=2)sumi=_add2(in1i,in2i);sumi+1=_add2(in1i+1,in2i+1);3、优化方法说明:源代码中,函数变量的定义是short*sum,short*in1,short*in2,改编后的代码函数变量是int*sum,constint*in1,constint*in2,整数类型由16位改编成32位,这时使用内联指令“_add2一次可以完成两组16位整数的加法,效率提高一倍。注意这里还使用了关键字cons

17、t和内联指令_nassert优化源代码。4、技巧:用内联指令_add2、_mpyhl、_mpylh完成两组16位数的加法和乘法,效率比单纯16位数的加法和乘法提高一倍。六、六、ifif elsels 语句的优化语句的优化(一)1、源代码:if(sub(Itpg,LTP_GAIN_THR1)=0)Ida-elseif(sub(ltpg,LTP_GAIN_THR2)LTP_GAIN_THR1)+(ltpgLTP_GAIN_THR2);(二)1、源代码:if(adapt=0)if(filt5443)result=0;elseif(filt16;/Q15result=_ssub(16384,_smpy

18、(24660,filt)16);elseresult=0;2、改编后的代码:filt1=_sshl(filt,18)16;tmp=_smpy(24660,filt1)16;result=_ssub(16384,tmp*(filt=0);result=result*(!(adapt!=0)|(filt5443);(三)1、源代码:staticWord16saturate(Word32L_var1)Word16swOut;if(L_var1SW_MAX)swOut=SW_MAX;giOverflow=1;elseif(L_var1SW_MIN)swOut=SW_MIN;giOverflow=1;e

19、lseswOut=(Word16)L_va门;/*automatictypeconversion*/return(swOut);2、改编后的代码:staticinlineWord32L_shl(Word32a,Word16b)return(Word32)(b)(-(b):_sshl(a),(b);3、优化方法说明:如果在循环中出现if.else.语句,由于if.else.语句中有跳转指令,而每个跳转指令有5个延迟间隙,因此程序执行时间延长;另外,循环内跳转也使软件流水受到阻塞。直接使用逻辑判断语句可以去除不必要的跳转。例如在例1的源代码最多有两次跳转,而改编后不存在跳转。例2和例3同样也去掉了

20、跳转。4、技巧:尽可能地用逻辑判断语句替代if.else.语句,减少跳转语句。七、七、1、源程序dm=0 x7FFF;for(j=0;jnsizm;j=add(j,1)if(dj=dm)dm=dj;jj=j;indexm=jj;2、优化后的程序dm0=dm1=0 x7fff;d0=(Word16*)&d0;di=(Word16*)&d1;#pragmaMUST_ITERATE(32,256,64);for(j=0;jNsiz;j+=2)n0=*d0;d0+=2;n1=*d1;di+=2;if(n0jjO)?jj1:jjO;3、优化说明求数组的最小值程序,优化时为了提高程序效率在

21、一个循环之内计算N=1,3,5和n=2,4,6的最小值,然后在比较二者的大小以求得整个数组的最小值。八、1、源程序for(k=0;k0)if(il_subfr)codei=add(codei,4096);codveck+=(2*L_SUBFR);elseif(il_subfr)codei=sub(codei,4096);index=add(index,16);if(indxtrack0)indxtrack=index;elseif(indexAindxtrack)&16)=0)if(sub(indxtrack,index)=0)indxtrack=shl(indxtrack&1

22、6),3)+shr(extract_l(L_mult(indxtrack&15),NB_POS),1)+(index&15);elseindxtrack=shl(index&16),3)+shr(extract_l(L_mult(index&15),NB_POS),1)+(indxtrack&15);elseif(sub(indxtrack&15),(index&15)=0)indxtrack=shl(index&16),3)+shr(extract_l(L_mult(index&15),15);elseindxtrack

23、=shl(indxtrack&16),3)+shr(extract_l(L_mult(indxtrack&15),2、优化后的程序for(k=0;k16;track=i-index*5;con=(j0);codveck=codveck+110*con;index=index+(!con)*16;conn=(i0)?1:-1;codei=codei+4096*conn*cono;nO=index;tO=indxtrack;nl=n0&16;NB_POS),1)+(indxtrack&NB_POS),1)+(index&15);t1=to&16;n2

24、=nO&15;t2=tO&15;tmpO=(_sshl(n1,19)16)+n2*NB_POS+t2;tmpl=(_sshl(t1,19)16)+t2*NB_POS+n2;conp=(n1=t1)&(tOn0)|(n1!=t1)&(t2=n2);tmp=conp*tmp0+(!conp)*tmp1;if(t00)indxtrack=n0;elseindxtrack=tmp;3、优化说明源程序中在循环中含有许多的if结构,在优化时对if结构首先进行化简,再将化简后的if结构用条件运算表达式进行改写,最后使循环可以Pipeline。九、1、源程序for(i=0;in

25、;i+)max=-32767;for(j=0;j=0)max=tmp2j;ix=j;tmp2ix=-32768;tmpi=ix;2、优化后的程序if(n0n1)temp=n0;n0=n1;n1=temp;if(n1n2)temp=n1;n1=n2;n2=temp;if(n2n3)temp=n2;n2=n3;n3=temp;if(n3n4)temp=n3;n3=n4;n4=temp;if(n0n1)temp=n0;n0=n1;n1=temp;if(n1n2)temp=n1;n1=n2;n2=temp;if(n2n3)temp=n2;n2=n3;n3=temp;if(n0n1)temp=n0;n0

26、=n1;n1=temp;if(n1n2)returnn1;3、优化说明源程序也为一个求中值的问题,由于已知循环次数固定为5,因此将循环展开使用if语句直接求取中值。十、1、源程序staticWord16Bin2int(Word16no_of_bits,Word16*bitstream)Word16value,i,bit;value=0;for(i=0;ino_of_bits;i+)value=shl(value,1);bit=*bitstream+;if(sub(bit,BIT_1)=0)value=add(value,1);return(value);for(i=0;i=35);for(i=

27、0;iloopmode;i+)value=value*2+*bitsp+;j-;if(j=0)*prm+=value;value=0;j=j1;j1=j2;j2=j3;j3=j4;j4=*bitnop+;3、优化说明源程序按照数据位流定义取出参数,为双重循环结构,优化中采用重新根据位流的bit长度定义循环次数,化简为单重循环,然后优化循环,去除boundary,使pipeline的数目最小。十、十、copycopy 程序的优化程序的优化1、源代码:Word16i;for(i=0;iL;i+)yi=xi;2、改编代码:(1) 要求数组长度能被2整除Word32i;Word32temp;int*p

28、1=(int*)&x0;int*q1=(int*)&y0;for(i=0;iL/2;i+)temp=*p1+;*q1+=temp;(2) 要求数组长度能被4整除Word32i;Word32temp1,temp2;Word32*pin1,*pin2,*pout1,*pout2;pin1=(Word32*)&x0;pin2=(Word32*)&x2;pout1=(Word32冷&y0;pout2=(Word32冷&y2;for(i=0;iL/4;i+)tempi=*pin1;temp2=*pin2;pin1+=2;pin2+=2;*pout1=tem

29、pi;*pout2=temp2;pout1+=2;pout2+=2;3、优化方法说明:把一次循环拷贝一个word16的数改为一次循环拷贝2个word16或4个word16的数。4、技巧:充分利用c6xx次读取32位数的特性,并利用一个指令周期能读取两个数据的特点。十二、十二、set_zeroset_zero 程序的优化程序的优化1、源代码:Word16i;for(i=0;iL;i+)xi=0;2、改编代码:(1)数组长度能被2整除Word32i;int*x1=(int*)&x0;for(i=0;iL/2;i+)*x1+=0;(2)数组长度能被4整除Word32i;int*x1=(int

30、*)&x0;int*x2=(int*)&x2;for(i=0;iL/4;i+)*x1=0;*x2=0;x1+;x2+;x1+;x2+;3、优化方法说明:把一次循环为一个word16的数赋值改为一次为2个或4个word16的数赋值。4、技巧:充分利用C6XX次读取32位数的特点,并利用一个指令周期能读取两个数据的特点。十十三、三、32bit 数与数与 16bit 数相乘数相乘1、源代码:L_tmp0=Mac_32_16(L_32,hi1,Io1,Io2);2、改编代码:L_tmp0=_sadd(_sadd(_smpyhl(hl32,Io2),(_mpyus(hl32,Io2)16

31、)vv1),L_32);3、优化方法说明:hI32是32bit的数,hi1和lol是16bit的数,且hI32=hi1vv16+lolvv1,即hi1和lol分别是hI32的高16位数和低16位数。函数Mac_32_16(L_32,hi1,Io1,Io2).实现L_32=L_32+(hi1*lo2)vv1+(Io1*lo2)15)vv1源代码是把一个32位的数拆成两个16位的数与一个16位的数相乘,优化后的代码不拆开32位的数,直接用32位的数与16位的数相乘。运用这种方法必须保证hl32的最低一位数必须为0,否则应用指令_clr(hl32,0,0)把最低位清零。4、技巧:源代码中的低16位数

32、lol是hl32的低16位右移一位得到的(留出一位符号位)。在与Io2相乘时又右移了15位,所以在改编代码中右移16位,并且是以无符号数与lo2相乘。十四、十四、32bit 数与数与 32bit 数相乘数相乘1、源代码:L_tmp=Mac_32(L_32,hi1,lo1,hi2,lo2);2、改编代码:L_tmp=_sadd(_sadd(_smpyh(hl1_32,hl2_32),(_mpyhslu(hl1_32,hl2_32)16)vv1)+(_mpyhslu(hl2_32,hl1_32)16)vv1),L_32);3、优化方法说明:两个32位的数相乘,不必分成四个16位的数相乘,直接用32

33、位相乘。其中:hl1_32=hi1v16+lo1v1,hl2_32=hi2v16+lo2v15+(lo1*hi2)15)vv14、技巧:低16位与高16位相乘时,低16位使用的是无符号数。十五、十五、16 位除法的优化位除法的优化1、源代码:Word16div_s(Word16var1,Word16var2)实现var1/var2Word16var_out=0;Word16iteration;Word32L_num=(Word32)var1;Word32L_denom=(Word32)var2;for(iteration=0;iteration15;iteration+)var_out=1;L

34、_num=L_denom)L_num=L_sub(L_num,L_denom);var_out=add(var_out,1);return(var_out);2、改编代码:Word16div_s1(Word16var1,Word16var2)Word32var1int;Word32var2int;var1int=var116;var2int=var215;var1int=_subc(var1int,var2int);var1int=_subc(var1int,var2int);var1int=_subc(var1int,var2int);var1int=_subc(var1int,var2in

35、t);var1int=_subc(var1int,var2int);var1int=_subc(var1int,var2int);var1int=_subc(var1int,var2int);var1int=_subc(var1int,var2int);var1int=_subc(var1int,var2int);var1int=_subc(var1int,var2int);var1int=_subc(var1int,var2int);varlint=_subc(va门int,var2int);varlint=_subc(var1int,var2int);varlint=_subc(var1int,var2int);varlint=_subc(var1int,var2int);return(varlint&Oxffff);3、优化方法说明:

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论