版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
DSP优化心得
C6XX优化经验总结
一、c6x的编译的常用选项
(一)c6x的编译程序为“cl6x.exe”使用的方法
CI6x[options][filenames]
CI6x:编译程序
Options:编译选项
Filenames:C或汇编源文件
说明:
编译选项是一个字母或者两个字母,对大小写不敏感。
编译选项的前面需要有一个“一”符号。
一个字母的选项可以合并在一起。比如“一sgq”与“一s-g-q”相同。
两个字母的选项如果第一个字母相同也可以合并在一起。比如“一mgt”与“一mg-mt”
相同。
(二)有关优化的选项
-mt:表示在程序中没有使用alaising技术,这使得编译器可以进行比较好的优化。
-03:对文件级别进行最强的优化,一般在编译时应该使用这个选项。但是在个别情况下使用
这个选项优化程序可能会出现
错误(-。2有相同现象,-o0和-。1不会出现错误)。可能是在优化循环,组织流水线的时候
发生错误。如果有这种现象出现可以同时
使用-g选项,程序优化就不会出现错误,但是优化效果会卜.降。另外可以调整程序的表达方
式,可能会避免编译器发生错误。
-pm:在程序级别进行优化。可以将所以文件联合在一起进行优化,主要有去掉没有被调用
的函数、总是常数的变量以及没有使用的
函数返回值。建议由程序员自己进行这种优化工作。使用这个选项在win98下编译可能会
出现找不到编译程序的情况。
-msO:不使用冗余循环进行优化,减小程序的大小。一般情况下这个选项对程序大小的优化
作用不明显。
-mh[n]:去掉流水线的epilog,减小程序的大小。这个选项的作用比较明显。但是有可能出
现读取地址超出有效范围的问题,
所以要在数据段的开始和结尾处增加一些pading,或者在分配内存时保证数组的前面和后
面一段范围内都是有效的地址。
可选的参数n给出这种pading的长度字节数。
(三)保留编译和优化信息的选项
-k:保留优化后生成汇编语言文件。
-s:汇编语言文件中加入优化信息,如果没有则加入C语言源程序作为注释。
-mw:在汇编语言文件加入软件流水线信息。
(四)有关调试和剖析的选项
-g:允许符号调试,在文件中包含符号信息和行号信息,可以在c语言级别进行调试
和剖析。使用联合使用一g、一mt和一o3可以保
证能够进行符号调试的情况下最大限度的优化。
-mg:允许profile优化后的程序。在“out”文件中包含符号信息和很少的行号信息。允许
在c语言的函数基本进行剖析。
如果联合使用这两个选项、一g选项可能被忽略,结果与只用一mg相同。
(五)其它类型
-mln:生成大内存模式的程序。
-mIO:缺省情况下将集合变量(数组和结构)作为far型。
-mil:缺省情况下将全部函数作为far型
-ml2:等于-mIO加-mil
-ml3:缺省情况下将全部数据和函数作为far型
(六)建议使用的编译方式
CI6x—gk—mt—o3—mw—ssafilename"
方式1用于程序的调试,这种方式具有比较强的优化能力,并且支持符号调试。在编译的过
程中不会发生错误。
由于生成的“out”文件中包含了符号信息和行号信息,所以比较大。
CI6x—k—mgt—o3—mw—ss“filename”
方式2用于程序的剖析(profile),这种方式的优化能力儿乎最强(绝大多数情况下与方式
3相同),
并且支持对程序进行profile。文件中只包含了符号信息前很少的行号信息,所以“。出”文
件比较小。
CI6x—k—mt—o3—mw—ssfilename"
方式3用于最终的发行版本程序,可以对程序进行最强的优化,并且去掉了全部的符号和行
号信息,所以“out”文件比较小。
由多个文件组成的程序应该编写makefile,将编译参数放在该文件中,并在其中说明使用的
编译器的版本号。
(七)连接参数
—heap:指定堆的大小
-stack:指定栈的大小
连接的各种选项应该统•放在“cmd”文件中
二、双重循环和多重循环的优化总结
双重循环多重循环看起来比较复杂,但实际上多重循环优化方法比较简单,就在于一个字:
“拆”,一旦完成这一步之后,
多重循环就成为单层循环,优化就可以按照普通的单层循环来做了。
多重循环的特点是在优化器优化时只在最内层循环中形成一个pipeline,这样循环语句就不
能充分利用C6的软件流水线,
而且对于内部循环的次数较少的情况,消耗在prolog和eplog上的cycle数也是不可忽视的。
针对这种状况可以考虑将多重循环拆开形成一个单层循环,可以拆外层循环也可以拆内层
循环,
一般视具体情况而定。这样就可以充分利用优化器构成的Pipeline。如下例:
voidfir2(constshortinput[],constshortcoefs[],shortout[])
inti,j;
intsum=0;
for(i=0;i<40;i++)
(
for(j=0;j<16;j++)
sum+=coefs[j]*inpu1[i+15-j];
out[i]=(sum»15);
)
内层循环循环次数较少,运算量也不大,资源方面只占用了一个乘法器,一个cycle只使用
一次乘法器,
而事实上我们可以在一个cycle内使用两个乘法器,所以还可以充分利用另外的一个乘法器。
因此考虑将内层循环拆开来执行,如下:
voidfir2_u(constshortinput[],constshortcoefs[],shortout[])
{
inti,j;
intsum;
for(i=0;i<40;i++)
(
sum=coefs[0]*input|i+15];
sum+=coefs[1]*input。+14];
sum+=coefs[2]*input[i+13];
sum+=coefs[3]*input[i+12];
sum+=coefs[4]*input[i+11];
sum+=coefs[5]*input。+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。+2];
sum+=coefs[14]*input[i+1];
sum+=coefs[15]*input[i+0];
out[i]=(sum»15);
)
这样虽然代码长度增加了,可变成了单循环,所有的运算都参加到pipeline中来,在Piped
loopkernal
中产生每一个cycle内都使用了两个乘法器,充分利用了DSP内部的资源,提高了运行效率。
又如下例:
doubl.aReg;
Word3.lvar;
/.(unsigned)low..(unsigned)low.*/
aRe..(double)(0xfff..L_var1..(double)(0xfff..L_var2..2.0;
A>.1.7
aRe..(aRe..65536);
aRe..floor(aReg);
/.(unsigned)low..(signed)high.*/
aRe.+.(double)(0xfff..L_var1..((double)L_shr(L_var2,16)..2.0;
/.(unsigned)low..(signed)high.7
aRe.+.(double)(0xfff..L_var2..((double)L_shr(L_var1,16)..2.0;
A>.1.7
aRe..(aRe..65536);
aRe..floor(aReg);
/.(signed)high..(signed)high.*/
aRe.+.(double)(L_shr(L_var1,16)..(double)(L_shr(L_var2,16)..2.0;
/.saturat.result..*/
lva..L_saturate(aReg);
return(lvar);
)
2、改编后的代码:
staticinlineWord32LmpyJI(Word32L_var1,Word32Lvar2)
(
Word32aReg_hh;
Word40aReg,aRegJI,aReg_lh,aReg_hl;
aRegJI=(Word40)_mpyu(L_var1,L_var2)»16;
aReg_lh=(Word40)_mpyluhs(L_var1,L_var2);
aReg_hl=(Word40)_mpyhslu(L_var1,L_var2);
aReg_hh=_smpyh(L_var1,L_var2);
aReg=Jsadd(aRegJI,Jsadd(aReg_lh,aReg_hl));
aReg=Jsadd(aReg»15,aReg_hh);
return(_sat(aReg));
)
3.优化方法说明:
C6000编译器提供的intrinsic可快速优化C代码,intrinsic用前下划线表示同调用函数一样
可以调用它,即直接内联为C6000的函数。
例如,在上例的源代码中没有使用intrinsics,每一行C代码需多个指令周期,在改编后的代
码中,每一行代码仅需一个指令周期。
例如,
MaRegJI=(Word40)_mpyu(L_var1,L_var2)»16中“_mpyu”就是一个intrinsics函数,
它表示两个无符号数的高16位相乘,
结果返回。C6000支持的所有intrinsics指令及其功能参见《TMS320c6000系列DSP的
原理与应用》一书的第265.266页,
该书还提供了另外的例子,这些内联函数定义在CCS所在的C6000\CGTCKDLS\lncludeU
录下的C6X.h文件中。
下面这个例子是C6000的“Programmer'sGuide”上提取的使用intrinsics优化C代码的
例子。
源代码:
intdotprod(constshort*a,constshort*b,unsignedintN)
(
inti,sum=0;
for(i=0;i<N;i++)
sum+=a[i]*b[i];
returnsum;
}
改编后代码:
intdotprod(constint*a,constint*b,unsignedintN)
(
inti,sum1=0,sum2=0:
for(i=0;i<(N»1);i++)
(
sum1+=_mpy(a[i],b[i]);
sum2+=_mpyh(a[i],b[i]);
)
returnsum1+sum2;
)
技巧:
在C语言的调试全部通过以后,可以尝试将尽可能多的语句使用intrinsics函数加以改编,
尤其在循环体内,这种改编可以大幅度减少执行时间。
四、
1.源代码:
voidflrjxdl(shortinput[],shortcoefs[],shortout[])
{
inti,j;
for(i=0;i<40;i++)
(
for(j=O;j<16;j++)
out[i*16+j]=coefs[j]*input[i+15-j];
)
)
2、改编后的代码:
voidfir_fxd2(constshortinput[],constshortcoefs[],shortout[])
(
for(i=0;i<40;i++)
(
for(j=0;j<16;j++)
out[i*16+j]=coefs[j]*input[i+15-j];
)
3.优化方法说明:
C6000编译器如果确定两条指令是不相关的,则安排它们并行执行。关键字const可以指
定一个变量或者一个变量的存储单元保持不变。
这有助于帮助编译器确定指令的不相关性。例如上例中,源代码不能并行执行,而结果改编
后的代码可以并行执行。
4.技巧:
使用const可以限定目标,确定存在于循环迭代中的存储器的不相关性。
五、
1、源代码:
voidvecsum(short*sum,short*in1,short*in2,unsignedintN)
(
inti;
for(i=0;i<N;i++)
sum[i]=in1[i]+in2[i];
)
2.改编后的代码:
voidvecsum6(int*sum,constint*in1,constint*in2,unsignedintN)
{
inti;
intsz=N»2;
_nassert(N>=20):
for(i=0;i<sz;i+=2)
(
sum[i]=_add2(in1[i],in2[i]);
sum[i+1]=_add2(in1[i+1],in2[i+1]);
)
)
3.优化方法说明:
源代码中,函数变量的定义是short*sum,short*in1,short*in2,改编后的代码函数变量是
int*sum,constint*in1,constint*in2,整数类型由16位改编成32位,这时使用内联指令
“_add2”一次可以完成两组16位整数的
加法,效率提高一倍。注意这里还使用了关键字const和内联指令_nassert优化源代码。
4.技巧:
用内联指令_add2._mpyhl、_mpylh完成两组16位数的加法和乘法,效率比单纯16位数的
加法和乘法提高一倍。
六、也..else…语句的优化
(一)
1.源代码:
if(sub(Itpg,LTP_GAIN_THR1)<=0)
(
adapt=0;
)
else
(
if(sub(Itpg,LTP_GAIN_THR2)<=0)
(
adapt=1;
)
else
{
adapt=2;
)
)
2.改编后的代码:
adapt=(ltpg>LTP_GAIN_THR1)+(ltpg>LTP_GAIN_THR2);
(二)
1.源代码:
if(adapt==0)
{
if(filt>5443)
(
result=0;
)
else
(
if(filt<0)
result=16384;
)
else
(
filt=_sshl(filt,18)»16;//Q15
result=_ssub(16384,_smpy(24660,filt)»16);
)
}
)
else
(
result=0;
)
2.改编后的代码:
filtl=_sshl(filt,18)»16;
tmp=_smpy(24660,filtli»16;
result=_ssub(16384,tmp*(filt>=0));
result=result*(!((adapt!=0)||(filt>5443)));
(三)
1、源代码:
staticWord16saturate(Word32L_var1)
(
Word16swOut;
if(L_var1>SWMAX)
{
swOut=SW_MAX;
giOverflow=1;
)
elseif(L_var1<SW_MIN)
(
swOut=SW_MIN;
giOverflow=1;
)
else
swOut=(Word16)L_var1;/*automatictypeconversion*/
return(swOut);
}
2.改编后的代码:
staticinlineWord32Lshl(Word32a,Word16b)
(
return((Word32)((b)<0?(Word32)(a)»(-(b)):_sshl((a),(b))));
}
3.优化方法说明:
如果在循环中出现if...else...语句,由于if...else...语句中有跳转指令,而每个跳转指令有5
个延迟间隙,
因此程序执行时间延长;另外,循环内跳转也使软件流水受到阻塞。直接使用逻辑判断语句
可以去除不必要的跳转。
例如在例1的源代码最多有两次跳转,而改编后不存在跳转。例2和例3同样也去掉了跳转。
4、技巧:
尽可能地用逻辑判断语句替代if...else...语句,减少跳转语句。
七、
1.源程序
dm=0x7FFF;
for(j=0;j<nsiz[m];j=add(j,1))
(
if(dO]<=dm)
(
dm=d[j];
jj=j;
)
}
index[m]=jj;
2、优化后的程序
dmO=dm1=0x7fff;
d0=(Word16*)&d[0];
d1=(Word16*)&d[1];
#pragmaMUST_ITERA'E(32,256,64);
for(j=0;j<Nsiz;j+=2)
(
nO=*d0;
dO+=2;
n1=*d1;
d1+=2;
if(nO<=dmO)
(
dmO=nO;
jjO=j;
)
if(n1<=dm1)
(
dm1=n1;
Jj1+;
)
}
if(dm1!=dmO)
index[m]=(dm1<dm3)?jj1:jjO;
)
else
{
index[m]=(jj1>jjO)?jj1:jjO;
)
3、优化说明
求数组的最小值程序,优化时为了提高程序效率在一个循环之内计算N=1,35.和n=2,4,6...
的最小值,
然后在比较二者的大小以求得整个数组的最小值。
八、
1、源程序
for(k=0;k<NBPULSE;k++)
(
i=codvec[k];
j=前晒;
index=mult(i,Q15_1_5);
track=sub(i,extract_l(L_shr(L_mult(index,5),1)));
if(j>0)
(
if(i<l_subfr)code[i]=add(code[i],4096);
codvec[k]+=(2*L_SUBFR);
)
else
(
if(i<l_subfr)code[i]=sub(code[i],4096);
index=add(index,16);
)
if(indx[track]<0)
{
indx[track]=index;
)
else
{
if(((indexAindx[track])&16)==0)
(
if(sub(indx[track],index)<=0)
{
indx[track]=shl((indx[track]&16),3)
+shr(extract_l(L_mult((indx[track]&15),NB_P0S)),1)+(index
&15);
)
else
indx[track]=shl((index&16),3)
+shr(extract_l(L_mult((index&15),NB_POS)),1)+(indx[track]
&15);
)
)
else
(
if(sub((indx[track]&15),(index&15))<=0)
{
indx[track]=shl((index&16),3)
+shr(extract_l(L_mult((index&15),NB_POS)),1)+(indx[track]
&15);
)
else
{
indx[track]=shl((indx[track]&16),3)
十shr(extract_l(L_mult((indx[track]&15),NB_POS)),1)十(index&
15);
)
)
)
)
2、优化后的程序
for(k=0;k<8;k++)
(
I=codvec[k];
j=sign[i];
index=_smpy(i,6554)»16;
track=i-index*5;
con=(j>0);
codvec[k]=codvec[k]+110*con;
index=index+(!con)*16;
conn=(i<l_subfr);
cono=(j>0)?1:-1;
code[i]=code[i]+4096*conn*cono;
nO=index;
tO=indx[track];
n1=n0&16;
t1=t0&16;
n2=n0&15;
t2=t0&15;
tmpO=(_sshl(n1,19)»16)+n2*NBPOS+t2;
tmp1=(_sshl(t1,19)»16)+t2*NB_POS+n2;
conp=(((n1==t1)&&(t0>n0))||((n1!=t1)&&(t2<=n2)));
tmp=conp*tmpO+(!conp)*tmp1;
if(tO<0)
indx[track]=nO;
else
indx[track]=tmp;
)
3、优化说明
源程序中在循环中含有许多的if结构,在优化时对if结构首先进行化简,
再将化简后的if结构用条件运算表达式进行改写,最后使循环可以Pipeline。
九、
1、源程序
for(i=0;i<n;i++)
(
max=-32767;
for(j=0;j<n;j++)
(
if(sub(tmp2[j],max)>=0)
(
max=tmp2[j];
ix=j;
)
)
tmp2[ix]=-32768;
tmp[i]=ix;
)
2、优化后的程序
if(n0>n1){temp=n0;n0=n1;n1=temp;}
if(n1>n2){temp=n1;n1=n2;n2=temp;}
if(n2>n3){temp=n2;n2=n3;n3=temp;}
if(n3>n4){temp=n3;n3=n4;n4=temp;}
if(n0>n1){temp=n0;n0=n1;n1=temp;}
if(n1>n2){temp=n1;n1=n2;n2=temp;}
if(n2>n3){temp=n2;n2=n3;n3=temp;}
if(n0>n1){temp=n0;n0=n1;n1=temp;}
if(n1>n2){returnn1;}
3、优化说明
源程序也为一个求中值的问题,由于已知循环次数固定为5,因此将循环展开使用if语句直
接求取中值。
十、
1、源程序
staticWord16Bin2int(Word16no_of_bits,Word16*bitstream)
Word16value,i,bit;
value=0;
for(i=0;i<no_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<prmno[mode];i++)
(
prm[i]=Bin2int(bitno[mode][i],bits);
bits+=bitno[mode][i];
}
2.优化后的程序
value=0;
bitsp=bits;
bitnop=&bitno[mode][0];
j=*bitnop++;
j1=*bitnop++;
j2=*bitnop++;
j3=*bitnop++;
j4=*bitnop++;
_nassert(loop[mode]>=35);
for(i-0;i<loop[mode];iii)
(
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的数目最小。
H^一、copy程序的优化
1.源代码:
Word16i;
for(i=0;i<L;i++)
{
y[i]=x[i];
}
2.改编代码:
(1)要求数组长度能被2整除
Word32i;
Word32temp;
int*p1=(int*)&x[0];
int*q1=(int*)&y[0];
for(i=0;i<L/2;i++)
(
temp=*p1++;
*q1++=temp;
}
(2)要求数组长度能被4整除
Word32i;
Word32tempi,temp2;
Word32*pin1,*pin2,*pout1,*pout2;
pin1=(Word32*)&x[0];
pin2=(Word32*)&x[2];
pout1=(Word32*)&y[0];
pout2=(Word32*)&y[2];
for(i=0;I<L/4;1++)
{
tempi=*pin1;
temp2=*pin2;
pin1+=2;
pin2+=2;
*pout1=tempi;
*pout2=temp2;
pout1+=2;
pout2+=2;
}
3.优化方法说明:
把一次循环拷贝一个word16的数改为一次循环拷贝2个word16或4个word16的数。
4.技巧:
充分利用C6xx一次读取32位数的特性,并利用一个指令周期能读取两个数据的特点。
十二、set_zero程序的优化
1.源代码:
Word16i;
for(i=0;i<L;i++)
x[i]=0;
)
2.改编代码:
(1)数组长度能被2整除
Word32i;
int*x1=(int*)&x[0];
for(i=0;i<L/2;i++)
(
*x1++=0;
)
(2)数组长度能被4整除
Word32i;
int*x1=(int*)&x[0];
int*x2=(int*)&x[2];
for(i=0;i<L/4;i++)
(
*x1=0;
*x2=0;
x1++;
x2++;
x1++;
x2++;
)
3.优化方法说明:
把一次循环为一个word16的数赋值改为一次为2个或4个word16的数赋值。
4.技巧:
充分利用C6XX一次读取32位数的特点,并利用一个指令周期能读取两个数据的特点。
十三、32bit数与16三数相乘
1.源代码:
LJmpO=Mac_32_16(L_32,hi1,Io1,Io2);
2.改编代码:
LJmp0=_sadd(_sadd(_smpyhl(hl32,Io2),
(_mpyus(hl32,Io2)»16)«1),L_32);
3.优化方法说明:
hl32是32bit的数,hi1和Io1是16bit的数,且hl32=hi1«16+Io1«1,BPhi1和Io1
分别是hl32的高16位数和低16位数。
函数Mac_32_16(L_32,hi1,Io1,Io2)实现
L_32=L_32+(hi1*lo2)«1+((Io1*lo2)»15)«1
源代码是把一个32位的数拆成两个16位的数与一个16位的数相乘,优化后的代码不拆开
32位的数,
直接用32位的数与16位的数相乘。运用这种方法必须保证hl32的最低一位数必须为0,否
则应用指令_clr(hl32,0,0)把
最低位清零。
4.技巧:
源代码中的低16位数Io1是hl32的低16位右移一位得到的(留出一位符号位)。在与1。2
相乘时乂右移了15位,
所以在改编代码中右移16位,并且是以无符号数与1。2相乘。
十四、32bit数与32bit数相乘
1.源代码:
L_tmp=Mac_32(L_32,hi1,Io1,hi2,Io2);
2.改编代码:
L_tmp=_sadd(_sadd(_smpyh(hl1_32,hl2_32),
(Cmpyhslu(hl1_32,hl2_32)»16)«1)+
((_mpyhslu(hl2_32,hl1_32)»16)«1)),L_32);
3.优化方法说明:
两个32位的数相乘,不必分成四个16位的数相乘,直接用32位相乘。其中:
hl1_32=hi1«16+Io1«1,hl2_32=hi2«16+Io2«1。
源代码实现:L_32=L_32+(hi1*hi2)«1+((hi1*lo2)»15+(Io1*hi2)»15)«1
4.技巧:
低16位与高16位相乘时,低16位使用的是无符号数。
十五、16位除法的优化
1.源代码:
Wordl6div_s(Wordl6var1,Word16var2)〃实现var1/var2
(
Word16var_out=0;
Wordl6iteration;
Word32Lnum=(Word32)var1;
Word32L_denom=(Word32)var2;
for(iteration=0;iteration<15;iteration++)
{
var_out«=1;
L_num«=1;
if(L_num>=L_denom)
(
L_num=L_sub(L_num,L_denom);
var_out=add(var_out,1);
)
)
return(var_out);
)
2.改编代码:
Wordl6div_s1(Wordl6var1,Wordl6var2)
(
Word32varlint;
Word32var2int;
varlint=var1«16;
var2int=var2«15;
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);
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);
var1int=_subc(var1int,var2int);
return(varlint&Oxffff);
}
3.优化方法说明:
实现16位的除法,要求被除数var1和除数var2都是整数,且var1〈=var2.利用C6XX特
有的指令subc,实现除法的循环移位相减操作。
4.技巧:
把被除数和除数都转换成32位数来操作,返回时取低15位数。
十六、C6X优化inline举例:
1、原程序:
for(i-LO_CHAN;i<-HI_CHAN;iii)
(
norm_shift=norm_l(st->ch_noise[i]);
Ltmp=Lshl(st->ch_noise[i],normshift);
normshiftl=norml(st->chenrg[i]);
Ltmp3=L_shl1(st->ch_enrg[i],norm_shift1-1);
Ltmp2=L_divide(Ltmp3,Ltmp);
Ltmp2=L_shr(Ltmp2,27-1+norm_shift1-norm_$hift);//*scaledas27,4*
if(Ltmp2==0)
Ltmp2=1;
Ltmpl=fnLog10(Ltmp2);
Ltmp3=L_add(Ltmp1,LOG_OFFSET-80807124);//*-round(log10(2A4)*2A26*
Ltmp2=L_mult(TEN_S5_10,extract_h(Ltmp3));
if(Ltmp2<0)
Ltmp2=0;
//*0.1875scaledas10,21*
Ltmpl=L_add(Ltmp2,CONST_0_1875_S10_21);
//*tmp/0.3752.667scaledas5,10,Ltmpisscaled15,16
Ltmp=L_mult(extract_h(Ltmp1),CONST_2_667_S5_10);
ch_snr[i]=extract_h(Ltmp);
)
2.优化后程序:
〃因循环体太大,拆成两个循环并把相应的函数内嵌以使程序能pipeline,
〃用L_div_tmp口保存因拆分而产生的中间变量。
for(i=LO_CHAN;i<=HI_CHAN;i++)
(
//norm_shift=norm_l(st->ch_noise[i]);
norm_shift=_norm(st->ch_noise[i]);
Ltmp=_sshl(st->ch_noise[i],norm_shift);
//normshiftl=norm_l(st->ch_enrg[i]);
norm_shift1=_norm(st->ch_enrg[i]);
//Ltmp3=L_shl1(st->ch_enrg[i],norm_shift1-1);
LLtmpI=st->ch_enrg[i];
LLtmpI=LLtmpI«(norm_shift1+7);
Ltmp3=(Word32)(LLtmp1»8);
Ltmp2=IL_divide(Ltmp3,Ltmp);
//Ltmp2=L_shr(Ltmp2,27-1+norm_shift1-norm_shift);
Ltmp2=(Ltmp2»(27-1+norm_shift1-norm_shift));
if(Ltmp2==0)
Ltmp2=1;
L_div_tmp[i]=Ltmp2;
)
for(i=LO_CHAN;i<=HI_CHAN;i++)
{
Ltmp2=L_div_tmp[i];
Ltmpl=lfnLog10(Ltmp2);
//Ltmp3=L_add(Ltmp1,LOG_OFFSET-80807124);
Ltmp3=_sadd(Ltmp1,LOG_OFFSET-80807124);
//Ltmp2=L_mult(TEN_S5_10,extract_h(Ltmp3));
Ltmp2=_smpy(TEN_S5_10,(Ltmp3»16));
if(Ltmp2<0)
Ltmp2=0;
Ltmpl=_sadd(Ltmp2,CONST_0_1875_S10_21);
//Ltmp=L_mult(extract_h(Ltmp1),CONST_2_667_S5_10);
Ltmp=_smpy((Ltmp1»16),CONST_2_667_S5_10);
//ch_snr[i
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 生物标志物在药物临床试验中的转化医学应用
- 生物标志物在结果公开中的应用
- 生物制品稳定性试验电荷变异检测
- 房地产企业生产运营管理面试题及答案
- 航空航天行业工程师面试题及答案
- 深度解析(2026)《GBT 19495.6-2004转基因产品检测 基因芯片检测方法》
- 深度解析(2026)《GBT 19448.2-2004圆柱柄刀夹 第2部分制造专用刀夹的A型半成品》
- 初级工程师面试题含答案
- 仓库管理岗位面试题及答案
- 互联网公司HRBP面试问题及答案参考
- 四川省内江市2023-2024学年七年级上学期期末测评英语试题
- DB11∕T 594.1-2017 地下管线非开挖铺设工程施工及验收技术规程 第1部分:水平定向钻施工
- 家园共育背景下幼儿良好生活习惯与能力的培养研究
- 《毛遂自荐》成语故事
- 美容行业盈利分析
- 小班化教学和合作学习
- 《继发性高血压》课件
- 垃圾中转站运营管理投标方案
- 数字媒体与数字广告
- 综合楼装饰装修维修改造投标方案(完整技术标)
- 中药现代化生产技术课件
评论
0/150
提交评论