IT技術(shu)互動(dong)交流平台

彩乐园官网

來源︰IT165收集(ji)  發布日期︰2020-02-26 02:29:56

此(ci)文是在http://blog.csdn.net/guanchanghui/article/details/1181851基礎上,通過自己(ji)的學(xue)習(xi)理解修改而來。暫且算(suan)作(zuo)是自己(ji)的原創吧。如有侵權,聯系,立(li)刻改轉載(zai)。


一、 c6x的編譯(yi)的常用選項
(一)c6x的編譯(yi)程序(xu)為“cl6x.exe”使用的方法(fa)


Cl6x [options] [filenames]


Cl6x︰ 編譯(yi)程序(xu)
Options︰ 編譯(yi)選項
Filenames︰ C或匯編源文件

說明︰
編譯(yi)選項是一個字母或者兩個字母,對(dui)大小寫不敏感。
編譯(yi)選項的前面需要有一個“-”符號。
一個字母的選項可以(yi)合並在一起。比(bi)如“-sgq”與“-s -g -q”相(xiang)同。
兩個字母的選項如果(guo)第一個字母相(xiang)同也可以(yi)合並在一起。比(bi)如“-mgt”與“-mg -mt”相(xiang)同。

(二(er))有關(guan)優化的選項
-mt︰ 表示(shi)在程序(xu)中(zhong)沒(mei)有使用alaising技術(shu),這使得編譯(yi)器可以(yi)進行比(bi)較好的優化。
-o3︰ 對(dui)文件級別進行最強的優化,一般(ban)在編譯(yi)時應(ying)該使用這個選項。但(dan)是在個別情況(kuang)下使用這個選項優化程序(xu)可能會出現zhi)砦螅o2有相(xiang)同現象,-o0和-o1不huan)岢魷執(zhi)砦螅 ?贍蓯竊謨嘔  huan),組(zu)織(zhi)流水線的時候發生錯誤。如果(guo)有這種現象出現可以(yi)同時使用-g選項,程序(xu)優化就不huan)岢魷執(zhi)砦螅 dan)是優化效果(guo)會下降(jiang)。另外可以(yi)調整程序(xu)的表達(da)方式,可能會避免編譯(yi)器發生錯誤。
-pm︰ 在程序(xu)級別進行優化。可以(yi)將所(suo)以(yi)文件聯合在一起進行優化,主要有去掉沒(mei)有被調用的函數、總是常數的變量以(yi)及沒(mei)有使用的函數返回值(zhi)。建議由程序(xu)員(yuan)自己(ji)進行這種優化工(gong)作(zuo)。使用這個選項在win98下編譯(yi)可能會出現zhong)也壞獎嘁yi)程序(xu)的情況(kuang)。
-ms0︰ 不使用冗余循環(huan)進行優化,減小程序(xu)的大小。一般(ban)情況(kuang)下這個選項對(dui)程序(xu)大小的優化作(zuo)用不明顯。
-mh[n]︰去掉流水線的epilog,減小程序(xu)的大小。這個選項的作(zuo)用比(bi)較明顯。但(dan)是有可能出現讀(du)取地址(zhi)超(chao)出有效範圍的問題,所(suo)以(yi)要在數據(ju)段的開始ji)徒崳wei)處增加you)恍ading,或者在分配內存時保證數組(zu)的前面和後(hou)面一段範圍內都(du)是有效的地址(zhi)。可選的參數n給出這種pading的長度字節(jie)數。

(三)保留編譯(yi)和優化信息(xi)的選項
-k︰ 保留優化後(hou)生成匯編語言文件。
-s︰ 匯編語言文件中(zhong)加入優化信息(xi),如果(guo)沒(mei)有xing)蚣尤語言源程序(xu)作(zuo)為注釋。
-mw︰在匯編語言文件加入軟件流水線信息(xi)。

(四)有關(guan)調試(shi)和剖(pou)析的選項
-g︰ 允(yun)許(xu)符號調試(shi),在“out”文件中(zhong)包含符號信息(xi)和行號信息(xi),可以(yi)在c語言級別進行調試(shi)和剖(pou)析。使用聯合使用-g、-mt和-o3可以(yi)保證能夠進行符號調試(shi)的情況(kuang)下最大限(xian)度的優化。
-mg︰允(yun)許(xu)profile優化後(hou)的程序(xu)。 在“out”文件中(zhong)包含符號信息(xi)和很少的行號信息(xi)。允(yun)許(xu)在c語言的函數基本進行剖(pou)析。如果(guo)聯合使用這兩個選項,-g選項可能被忽略,結果(guo)與只用-mg相(xiang)同。

(五)其它(ta)類(lei)型
-mln︰ 生成大內存模式jiang)某絛xu)。
-ml0︰ 缺省情況(kuang)下將集(ji)合變量(數組(zu)和結構)作(zuo)為far型。
-ml1︰ 缺省情況(kuang)下將全部函數作(zuo)為far型
-ml2︰ 等于-ml0加-ml1
-ml3︰ 缺省情況(kuang)下將全部數據(ju)和函數作(zuo)為far型

(六)建議使用的編譯(yi)方式
Cl6x -gk -mt -o3 -mw -ss “filename”
方式1用于程序(xu)的調試(shi),這種zhi)絞驕哂斜bi)較強的優化能力(li),並且支持zhi)諾魘shi)。在編譯(yi)的過程中(zhong)不huan)岱?砦蟆S捎諫傻ldquo;out”文件中(zhong)包含了(liao)符號信息(xi)和行號信息(xi),所(suo)以(yi)比(bi)較大。
Cl6x -k -mgt -o3 -mw -ss “filename”
方式2用于程序(xu)的剖(pou)析(profile),這種zhi)絞降(jiang)撓嘔 芰li)幾(ji)乎最強(絕大多數情況(kuang)下與方式3相(xiang)同),並且支持對(dui)程序(xu)進行profile。文件中(zhong)只包含了(liao)符號信息(xi)和很少的行號信息(xi),所(suo)以(yi)“out”文件比(bi)較小。
Cl6x -k -mt -o3 -mw -ss “filename”
方式3用于最終(zhong)的發行版(ban)本程序(xu),可以(yi)對(dui)程序(xu)進行最強的優化,並且去掉了(liao)全部的符號和行號信息(xi),所(suo)以(yi)“out”文件比(bi)較小。由多個文件組(zu)成的程序(xu)應(ying)該編寫makefile,將編譯(yi)參數放(fang)在該文件中(zhong),並在其中(zhong)說明使用的編譯(yi)器的版(ban)本號。

(七)連接參數
-heap︰ 指定(ding)堆的大小
-stack︰ 指定(ding)棧的大小
連接的各種選項應(ying)該統一huan)fang)在“cmd”文件中(zhong)

二(er)、 雙重循環(huan)和多重循環(huan)的優化總結


雙重循環(huan)多重循環(huan)看起來比(bi)較xi)叢櫻 dan)實(shi)際上多重循環(huan)優化方法(fa)比(bi)較簡單,就在于一個字︰“拆”,一旦完成這一步之後(hou),多重循環(huan)就成為單層循環(huan),優化就可以(yi)按照普通的單層循環(huan)來做了(liao)。
多重循環(huan)的特點是在優化器優化時只在最內層循環(huan)中(zhong)形成一個pipeline,這樣循環(huan)語句就不能充分利用C6的軟件流水線,而且對(dui)于內部循環(huan)的次數較少的情況(kuang),消耗在prolog(循環(huan)填充)和eplog(循環(huan)fang)pai)空)上的cycle數也是不可忽視的。
針對(dui)這種狀況(kuang)可以(yi)考慮(lv)將多重循環(huan)拆開形成一個單層循環(huan),可以(yi)拆外層循環(huan)也可以(yi)拆內層循環(huan),一般(ban)視具體情況(kuang)而定(ding)。這樣就可以(yi)充分利用優化器構成的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[i] = (sum >> 15);}}

 

內層循環(huan)循環(huan)次數較少,運算(suan)量也不大,資shi)捶矯嬤徽加昧liao)一個乘法(fa)器,一個cycle只使用一次乘法(fa)器,而事實(shi)上我們(men)可以(yi)在一個cycle內使用兩個乘法(fa)器,所(suo)以(yi)還可以(yi)充分利用另外的一個乘法(fa)器。因此(ci)考慮(lv)將內層循環(huan)拆開來執(zhi)行,如下︰

 

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[i] = (sum >> 15);}}
這樣雖然代碼長度增加了(liao),可變成了(liao)單循環(huan),所(suo)有的運算(suan)都(du)參加到pipeline中(zhong)來,在Piped loop kernal中(zhong)產(chan)生每一個cycle內都(du)使用了(liao)兩個乘法(fa)器,充分利用了(liao)DSP內部的資shi)矗 岣 liao)運行效率。又如下例︰
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]);//乘加運算(suan)相(xiang)當于_add(s,_mpy(x[j],h[j-i]))y32[i] = s;s = L_abs(s);if (L_sub(s, max) >(Word32) 0)max = s;}tot = L_add(tot, L_shr(max, 1));}
在這個多層循環(huan)中(zhong)一共(gong)有三層循環(huan),而最內層的循環(huan)的運算(suan)量很小,只有一次乘累(lei)加操作(zuo),而我們(men)知道(dao)C6中(zhong)一個packet中(zhong)可以(yi)做兩個乘累(lei)加運算(suan),所(suo)以(yi)為了(liao)增加內部循環(huan)的運算(suan),減少外部循環(huan)的層數,我們(men)可以(yi)將第一層循環(huan)的操作(zuo)拆開,其負責的運算(suan)加入到內部循環(huan)中(zhong),也就是在內層循環(huan)中(zhong)一次做四次的乘累(lei)加運算(suan),這樣將多次wei)僮zuo)形成pipeline,提高了(liao)運行效率sheng) 嘔 hou)的C代碼如下︰
tot = 4;max0 = 0;max1 = 0;max2 = 0;max3 = 0;for (i = 0; i < 44; i += STEP) //STEP=4, 11 times cirs{//codefor (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

 


CCS的優化︰
三、16位變為32位操作(zuo),使用intrinsic函數,用const等。

1、源代碼︰

Word32 L_mpy_ll(Word32 L_var1, Word32 L_var2){double aReg;Word32 lvar;/* (unsigned)low1 * (unsigned)low1 */aReg = (double)(0xffff & L_var1) * (double)(0xffff & L_var2) * 2.0;/* >> 16 */aReg = (aReg / 65536);aReg = floor(aReg);/* (unsigned)low1 * (signed)high4 */aReg += (double)(0xffff & L_var1) * ((double)L_shr(L_var2, 16)) * 2.0;/* (unsigned)low2 * (signed)high3 */aReg += (double)(0xffff & L_var2) * ((double)L_shr(L_var1, 16)) * 2.0;/* >> 16 */aReg = (aReg / 65536);aReg = floor(aReg);/* (signed)high3 * (signed)high4 */aReg += (double)(L_shr(L_var1, 16)) * (double)(L_shr(L_var2, 16)) * 2.0;/* saturate result.. */lvar = L_saturate(aReg);return(lvar);}
2、改編後(hou)的代碼︰

 

 

static inline Word32 L_mpy_ll(Word32 L_var1, Word32 L_var2){Word32 aReg_hh;Word40 aReg, aReg_ll, aReg_lh, aReg_hl;aReg_ll = (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 = _lsadd(aReg_ll, _lsadd(aReg_lh, aReg_hl));aReg = _lsadd(aReg >> 15, aReg_hh);return(_sat(aReg));}
3、優化方法(fa)說明︰

 

C6000編譯(yi)器提供的intrinsic 可快速優化C代碼,intrinsic用men)跋祿 弒硎shi)同調用函數一樣可以(yi)調用它(ta),即直(zhi)接內聯為C6000的函數。
例如,在上例的源代碼中(zhong)沒(mei)有使用intrinsics,每一行C代碼需多個指令周期,在改編後(hou)的代碼中(zhong),每一行代碼僅需一個指令周期。
例如,“aReg_ll = (Word40)_mpyu(L_var1, L_var2) >> 16”中(zhong)“_mpyu”就是一個intrinsics函數,它(ta)表示(shi)兩個無(wu)符號數的高16位相(xiang)乘,結果(guo)返回。C6000支持zhi)乃suo)有intrinsics指令及其功能參見《TMS320C6000系列DSP的原理與應(ying)用》一書的第265、266頁,該書還gu) ├liao)另外的例子(zi)。這些內聯函數定(ding)義在CCS所(suo)在的C6000 / CGTOOLS / Include目錄(lu)下的C6X.h文件中(zhong)。
下面這個例子(zi)是C6000的“Programmer's Guide”上提取的使用intrinsics優化C代碼的例子(zi)。

源代碼︰

int dotprod(const short *a, const short *b, unsigned int N){int i, sum = 0;for (i = 0; i < N; i++)sum += a[i] * b[i];return sum;}
改編後(hou)代碼︰
int dotprod(const int *a, const int *b, unsigned int N){int i, sum1 = 0, sum2 = 0;for (i = 0; i < (N >> 1); i++){sum1 += _mpy(a[i], b[i]);sum2 += _mpyh(a[i], b[i]);}return sum1 + sum2;}
技巧(qiao)︰
在C語言的調試(shi)全部通過以(yi)後(hou),可以(yi)嘗(chang)試(shi)將盡(jin)可能多的語句使用intrinsics函數加you)願謀啵 繞湓諮 huan)體內,這種改編可以(yi)大幅度減少執(zhi)行時ben)洹br />

 

四、

1、源代碼︰

 

void fir_fxd1(short input[], short coefs[], short out[]){int i, j;for (i = 0; i < 40; i++){for (j = 0; j < 16; j++)out[i * 16 + j] = coefs[j] * input[i + 15 - j];}}
2、改編後(hou)的代碼︰

 

 

void fir_fxd2(const short input[], const short coefs[], short out[]){int i, j;for (i = 0; i < 40; i++){for (j = 0; j < 16; j++)out[i * 16 + j] = coefs[j] * input[i + 15 - j];}}
3、優化方法(fa)說明︰

 

C6000編譯(yi)器如果(guo)確(que)定(ding)兩條(tiao)指令是不相(xiang)關(guan)的,則(ze)安排(pai)它(ta)們(men)並行執(zhi)行。 關(guan)鍵字const可以(yi)指定(ding)一個變量或者一個變量的存儲單元保持不變。這有助于幫助編譯(yi)器確(que)定(ding)指令的不相(xiang)關(guan)性(xing)。例如上例中(zhong),源代碼不能並行執(zhi)行,而結果(guo)改編後(hou)的代碼可以(yi)並行執(zhi)行。

技巧(qiao)︰
使用const可以(yi)限(xian)定(ding)目標(biao),確(que)定(ding)存在于循環(huan)迭代中(zhong)的存儲器的不相(xiang)關(guan)性(xing)。

五、

1、源代碼︰

 

void vecsum(short *sum, short *in1, short *in2, unsigned int N){int i;for (i = 0; i < N; i++)sum[i] = in1[i] + in2[i];}

 

2、改編後(hou)的代碼︰

void vecsum6(int *sum, const int *in1, const int *in2, unsigned int N){int i;int sz = N >> 2;//用int型讀(du)取short數據(ju),循環(huan)次數減半_nassert(N >= 20);for (i = 0; i < sz; i += 2)//循環(huan)展開i每次加2{sum[i] = _add2(in1[i], in2[i]);sum[i + 1] = _add2(in1[i + 1], in2[i + 1]);}}
3、優化方法(fa)說明︰
源代碼中(zhong),函數變量的定(ding)義是 short *sum, short *in1, short *in2, 改編後(hou)的代碼函數變量是int *sum, const int *in1, const int *in2, 整數類(lei)型由16位改編成32位,這時使用內聯指令“_add2”一次可以(yi)完成兩組(zu)16位整數的加法(fa),效率提高一倍。注意這里還使用了(liao)關(guan)鍵字const和內聯指令_nassert優化源代碼。

技巧(qiao)︰
用內聯指令_add2、_mpyhl、_mpylh完成兩組(zu)16位數的加法(fa)和乘法(fa),效率比(bi)單純16位數的加法(fa)和乘法(fa)提高一倍。

 

六、if...else...語句的優化
(一)

1、源代碼︰

 

if (sub(ltpg, LTP_GAIN_THR1) <= 0)//ltpg<LTP_GAIN_THR1時進入,如果(guo)ltpg>LTP_GAIN_THR1,則(ze)adapt=1{adapt = 0;}else{if (sub(ltpg, LTP_GAIN_THR2) <= 0){adapt = 1;}}else{adapt = 2;}
2、改編後(hou)的代碼︰

 

 

adapt = (ltpg > LTP_GAIN_THR1) + (ltpg > LTP_GAIN_THR2);
(二(er))
1、源代碼︰
if (adapt == 0){if (filt > 5443){result = 0;}else{if (filt < 0){result = 16384;}else{filt = _sshl(filt, 18) >> 16; // Q15result = _ssub(16384, _smpy(24660, filt) >> 16);}}}else{result = 0;}
2、改編後(hou)的代碼︰

 

 

filt1 = _sshl(filt, 18) >> 16;tmp = _smpy(24660, filt1) >> 16;result = _ssub(16384, tmp * (filt >= 0));//filt<0則(ze)result = 16384;result = result * (!((adapt != 0) (filt > 5443)));//最巧(qiao)妙(miao)的是,將if...else...融入表達(da)式,adapt!=0和filt>5443任意一個條(tiao)件成立(li)result就等于0

 

(三)

1、源代碼︰

 

static Word16 saturate(Word32 L_var1){Word16 swOut;if (L_var1 > SW_MAX){swOut = SW_MAX;giOverflow = 1;}else if (L_var1 < SW_MIN){swOut = SW_MIN;giOverflow = 1;}elseswOut = (Word16)L_var1; /* automatic type conversion */return (swOut);}
2、改編後(hou)的代碼︰

 

 

static inline Word32 L_shl(Word32 a, Word16 b){return ((Word32)((b) < 0 ? (Word32)(a) >> (-(b)) : _sshl((a), (b))));}
3、優化方法(fa)說明︰
如果(guo)在循環(huan)中(zhong)出現if...else...語句,由于if...else...語句中(zhong)有跳轉指令,而每個跳轉指令有5個延遲間隙,因此(ci)程序(xu)執(zhi)行時ben)溲映?渙磽猓  huan)內跳轉也使軟件流水受到阻塞。直(zhi)接使用邏輯判斷語句可以(yi)去除不必要的跳轉。例如在例1的源代碼最多有兩次跳轉,而改編後(hou)不存在跳轉。例2和例3同樣也去掉了(liao)跳轉。

技巧(qiao)︰
盡(jin)可能地用邏輯判斷語句替代if...else...語句,減少跳轉語句。


七、
1、源程序(xu)

 

 

dm = 0x7FFF;for (j = 0; j < nsiz[m]; j = add(j, 1))//求(qiu)每組(zu)數據(ju)的最小值(zhi),並把(ba)每組(zu)最小值(zhi)的位置(zhi)索引(yin)記錄(lu)在index[m]中(zhong){if (d[j] <= dm){dm = d[j];jj = j;}}index[m] = jj;
2、優化後(hou)的程序(xu)

 

 

dm0 = dm1 = 0x7fff;d0 = (Word16 *)&d[0];d1 = (Word16 *)&d[1];# pragma MUST_ITERATE(32,256,64);for (j = 0; j < Nsiz; j += 2){n0 = *d0;d0 += 2;n1 = *d1;d1 += 2;if (n0 <= dm0){dm0 = n0;jj0 = j;}if (n1 <= dm1){dm1 = n1;jj1 = j + 1;}}if (dm1 != dm0){index[m] = (dm1 < dm0) ? jj1 : jj0;}else{index[m] = (jj1 > jj0) ? jj1 : jj0;}
3、優化說明
求(qiu)數組(zu)的最小值(zhi)程序(xu),優化時為了(liao)提高程序(xu)效率shi)諞桓鱍 huan)之內計算(suan)N = 1, 3, 5..和n = 2, 4, 6...的最小值(zhi),然後(hou)在比(bi)較二(er)者的大小以(yi)求(qiu)得整個數組(zu)的最小值(zhi)。

 

八、
1、源程序(xu)

 

for (k = 0; k < NB_PULSE; k++){i = codvec[k];j = sign[i];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 (((index ^ indx[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_POS)), 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、優化後(hou)的程序(xu)
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;n0 = index;t0 = indx[track];n1 = n0 & 16;t1 = t0 & 16;n2 = n0 & 15;t2 = t0 & 15;tmp0 = (_sshl(n1, 19) >> 16) + n2*NB_POS + t2;tmp1 = (_sshl(t1, 19) >> 16) + t2*NB_POS + n2;conp = (((n1 == t1) && (t0 > n0)) ((n1 != t1) && (t2 <= n2)));tmp = conp*tmp0 + (!conp)*tmp1;if (t0 < 0)indx[track] = n0;elseindx[track] = tmp;}
3、優化說明
源程序(xu)中(zhong)在循環(huan)中(zhong)含有許(xu)多的if結構,在優化時對(dui)if結構首先進行化簡,再將化簡後(hou)的if結構用條(tiao)件運算(suan)表達(da)式進行改寫,最後(hou)使循環(huan)可以(yi)Pipeline。

 



九、
1、源程序(xu)

 

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、優化後(hou)的程序(xu)

 

 

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) {return n1;}
3、優化說明
源程序(xu)也為一個求(qiu)中(zhong)值(zhi)的問題,由于已知循環(huan)次數固(gu)定(ding)為5,因此(ci)將循環(huan)展開使用if語句直(zhi)接求(qiu)取中(zhong)值(zhi)。


十、
1、源程序(xu)

 

 

static Word16 Bin2int(Word16 no_of_bits, Word16 *bitstream){Word16 value, 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、優化後(hou)的程序(xu)

 

 

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]; i++){value = value * 2 + *bitsp++;j--;if (j == 0){*prm++ = value;value = 0;j = j1;j1 = j2;j2 = j3;j3 = j4;j4 = *bitnop++;}}
3、優化說明
源程序(xu)按照數據(ju)位流定(ding)義取出參數,為雙重循環(huan)結構,優化中(zhong)采用重新根據(ju)位流的bit長度定(ding)義循環(huan)次數,化簡為單重循環(huan),然後(hou)優化循環(huan),去除boundary,使pipeline的數目最小。


十一、copy程序(xu)的優化
1、源代碼︰
Word16 i;for (i = 0; i < L; i++){y[i] = x[i];}
2、改編代碼︰
(1)要求(qiu)數組(zu)長度能被2整除
Word32 i;Word32 temp;int *p1 = (int *)&x[0];int *q1 = (int *)&y[0];for (i = 0; i < L / 2; i++){temp = *p1++;*q1++ = temp;}
(2)要求(qiu)數組(zu)長度能被4整除

 

 

Word32 i;Word32 temp1, 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; i++){temp1 = *pin1;temp2 = *pin2;pin1 += 2;pin2 += 2;*pout1 = temp1;*pout2 = temp2;pout1 += 2;pout2 += 2;}
3、優化方法(fa)說明︰
把(ba)一次循環(huan)拷貝一個word16的數改為一次循環(huan)拷貝2個word16或4個word16的數。
技巧(qiao)︰
充分利用c6xx一次讀(du)取32位數的特性(xing),並利用一個指令周期能讀(du)取兩個數據(ju)的特點。


十二(er)、set_zero程序(xu)的優化
1、源代碼︰

 

Word16 i;for (i = 0; i < L; i++){x[i] = 0;}
2、改編代碼︰
(1)數組(zu)長度能被2整除

 

Word32 i;int *x1 = (int *)&x[0];for (i = 0; i < L / 2; i++){*x1++ = 0;}
(2)數組(zu)長度能被4整除

 

 

Word32 i;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、優化方法(fa)說明︰
把(ba)一次循環(huan)為一個word16的數賦(fu)值(zhi)改為一次為2個或4個word16的數賦(fu)值(zhi)。

 

技巧(qiao)︰
充分利用C6XX一次讀(du)取32位數的特點,並利用一個指令周期能讀(du)取兩個數據(ju)的特點。


十三、32bit數與16bit數相(xiang)乘
1、源代碼︰

 

L_tmp0 = Mac_32_16(L_32, hi1, lo1, lo2);

 

2、改編代碼︰

 

L_tmp0 = _sadd(_sadd(_smpyhl(hl32, lo2),(_mpyus(hl32, lo2) >> 16) << 1), L_32);
3、優化方法(fa)說明︰
hl32是32bit的數,hi1和lo1是16bit的數,且 hl32 = hi 1<<16 + lo1 << 1 ,即hi1和lo1分zhi)鶚l32的高16位數和低16位數。函數Mac_32_16(L_32, hi1, lo1, lo2)實(shi)現L_32 = L_32 + (hi1*lo2)<<1 + ((lo1*lo2)>>15)<<1源代碼是把(ba)一個32位的數拆成兩個16位的數與一個16位的數相(xiang)乘,優化後(hou)的代碼不拆開32位的數,直(zhi)接用32位的數與16位的數相(xiang)乘。運用這種zhi)椒fa)必須保證hl32的最低一位數必須為0,否(fu)則(ze)應(ying)用指令_clr(hl32, 0, 0)把(ba)最低位清零。

 

技巧(qiao)︰
源代碼中(zhong)的低16位數lo1是hl32的低16位右(you)移一位得到jiang)模 舫 晃環(huan)盼唬 T謨o2相(xiang)乘時又右(you)移了(liao)15位,所(suo)以(yi)在改編代碼中(zhong)右(you)移16位,並且是以(yi)無(wu)符號數與lo2相(xiang)乘。
 


十四、32bit數與32bit數相(xiang)乘
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) << 1) +((_mpyhslu(hl2_32, hl1_32) >> 16) << 1)), L_32);
3、優化方法(fa)說明︰
兩個32位的數相(xiang)乘,不必分成四個16位的數相(xiang)乘,直(zhi)接用32位相(xiang)乘。其中(zhong)︰hl1_32 = hi1 << 16 + lo1 << 1, hl2_32 = hi2 << 16 + lo2 << 1;
源代碼實(shi)現︰ L_32 = L_32 + (hi1*hi2)<<1 + ( (hi1*lo2)>>15 + (lo1*hi2)>>15 )<<1

 

技巧(qiao)︰
低16位與高16位相(xiang)乘時,低16位使用的是無(wu)符號數。

十五、16位除法(fa)的優化
1、源代碼︰

 

Word16 div_s(Word16 var1, Word16 var2) //實(shi)現 var1/var2{Word16 var_out = 0;Word16 iteration;Word32 L_num = (Word32)var1;Word32 L_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、改編代碼︰
Word16 div_s1(Word16 var1, Word16 var2){Word32 var1int;Word32 var2int;var1int = 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 (var1int & 0xffff);}
3、優化方法(fa)說明︰
實(shi)現16位的除法(fa),要求(qiu)被除數var1和除數var2都(du)是整數,且var1<=var2。利用C6XX特有的指令subc,實(shi)現除法(fa)的循環(huan)移位相(xiang)減操作(zuo)。

 

技巧(qiao)︰
把(ba)被除數和除數都(du)轉換(huan)成32位數來操作(zuo),返回時bi)〉6位數。

十六、C6X優化inline舉例:
1、源程序(xu)︰

 

for (i = LO_CHAN; i <= HI_CHAN; i++){norm_shift = norm_l(st->ch_noise[i]);Ltmp = L_shl(st->ch_noise[i], norm_shift);norm_shift1 = norm_l(st->ch_enrg[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_shift); // * scaled as 27,4 *if (Ltmp2 == 0)Ltmp2 = 1;Ltmp1 = fnLog10(Ltmp2);Ltmp3 = L_add(Ltmp1, LOG_OFFSET - 80807124); // * -round(log10(2^4)*2^26 *Ltmp2 = L_mult(TEN_S5_10, extract_h(Ltmp3));if (Ltmp2 < 0)Ltmp2 = 0;// * 0.1875 scaled as 10,21 *Ltmp1 = L_add(Ltmp2, CONST_0_1875_S10_21);// * tmp / 0.375 2.667 scaled as 5,10, Ltmp is scaled 15,16 *Ltmp = L_mult(extract_h(Ltmp1), CONST_2_667_S5_10);ch_snr[i] = extract_h(Ltmp);}
2、優化後(hou)程序(xu)︰

 

 

//因循環(huan)體太大,拆成兩個循環(huan)並把(ba)相(xiang)應(ying)的函數內嵌以(yi)yun)鉤絛xu)能pipeline,//用L_div_tmp[]保存因拆分而產(chan)生的中(zhong)間變量。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);//norm_shift1 = norm_l(st->ch_enrg[i]); norm_shift1 = _norm(st->ch_enrg[i]);//Ltmp3 = L_shl1(st->ch_enrg[i], norm_shift1 - 1);LLtmp1 = st->ch_enrg[i];LLtmp1 = LLtmp1 << (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];Ltmp1 = IfnLog10(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;Ltmp1 = _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] = extract_h(Ltmp);ch_snr[i] = (Ltmp >> 16);}
3、優化說明
觀察上面這個循環(huan),循環(huan)體本身比(bi)較大,且含有兩個函數L_divide()和fnLog10(),而C62內部只有32個寄存器,且有些寄存器是系統用的,如B14、B15這樣循環(huan)體太大將會導致lu)拇嫫韃還環(huan)峙洌 佣賈孿低潮嘁yi)器無(wu)法(fa)實(shi)現循環(huan)的pipeline。

為了(liao)實(shi)現循環(huan)的pipeline。我們(men)需要把(ba)循環(huan)體進行拆分,拆分時要考慮(lv)以(yi)下lu)傅悖br />(1)拆分成幾(ji)個循環(huan)比(bi)較合適(shi)?在各個循環(huan)能pipeline的前提下,拆開的循環(huan)個數越少越好。這就要求(qiu)盡(jin)可能讓各個循環(huan)的運算(suan)量接近。
(2)考慮(lv)在什麼地方把(ba)程序(xu)拆開比(bi)較合適(shi)?循環(huan)體里的數據(ju)流往往並不是單一的,在拆開的斷點處勢必要用中(zhong)間變量保存上次的循環(huan)運算(suan)結果(guo),供以(yi)後(hou)的循環(huan)用。適(shi)shi)鋇牟鸝  huan)體,使所(suo)需的中(zhong)間變量越少越好。
(3)循環(huan)體中(zhong)的函數調用必須定(ding)義成內嵌形式,含有函數調用的循環(huan)系統是無(wu)法(fa)使之pipeline的;各個循環(huan)體中(zhong)的判斷分支機構gong)豢商 啵 fu)則(ze)系統也無(wu)法(fa)使之pipeline,為此(ci)應(ying)近可能把(ba)可以(yi)確(que)定(ding)下來的分支確(que)定(ding)下來,並盡(jin)可能用內嵌指令。

針對(dui)上面這個例子(zi),考慮(lv)︰
(1)為讓各個循環(huan)的運算(suan)量大致相(xiang)當,應(ying)把(ba)L_divide()和fnLog10()分zhi)攪礁鱍 huan)中(zhong)去,從循環(huan)體大小上考慮(lv),估計拆成兩個循環(huan)比(bi)較合適(shi)。
(2)考慮(lv)在什麼地方把(ba)程序(xu)拆開比(bi)較合適(shi)?在if (Ltmp2 == 0) Ltmp2 = 1;後(hou)拆開,因為後(hou)面用到jiang)氖ju)只有Ltmp2,故shou)恍櫨靡桓鍪zu)保存每次循環(huan)的Ltmp2值(zhi)即可。
(3)循環(huan)體中(zhong)的兩處函數調用L_divide()和fnLog10()都(du)定(ding)義了(liao)其內嵌形式,IL_divid()和IfnLog10()。當把(ba)可以(yi)確(que)定(ding)下來的分支作(zuo)確(que)定(ding)處理,並盡(jin)可能用內嵌指令後(hou),該循環(huan)體中(zhong)所(suo)剩(sheng)的分支結構已很少,循環(huan)體可以(yi)pipeline。
優化前程序(xu)用2676 cycle,優化後(hou)用400 cycle。優化後(hou)兩個子(zi)循環(huan)的MII分zhi)鷂4和6cycle。


內存地址(zhi)形式︰ 奔(ben)騰(teng),C6000都(du)是32位計算(suan)機,字長32,但(dan)內存地址(zhi)都(du)是按字節(jie)組(zu)織(zhi)的 一個字4字節(jie)(查看內存時候各個字
時候:例如兩個連續字ox1000 ox1004) 寫匯編程序(xu)時候,下一個字也需要+4,但(dan)寫 C語言yun)焙int 型,+1就是加4但(dan)是,在Tiger SHARC中(zhong),雖然也是32位huan)但(dan)內存是地址(zhi)是按字組(zu)織(zhi)的,查看內存時,連續的字zhi)?zhi)相(xiang)差1

//////////////////////////////////////////////////////////////////////////////////自己(ji)寫的一段性(xing)能很高的代碼///////////////////////////

 

 

#include <stdio.h>#define INTRINSICshort add(short var1, short var2){short var_out;int L_somme;L_somme = (int)var1 + var2;return(var_out);} int main(){int i, result;#ifdef INTRINSICfor (i = 0; i<1000; i++){result = _sadd(100000, 20);result>0X00007fff ? result = 0x7fff : (result < 0x8000 ? result = 0x8000 : 0);}#elsefor (i = 0; i < 1000; i++)add(10, 20);#endifreturn 0;}

Tag標(biao)簽︰經驗  筆記  
  • 彩乐园官网

About IT165 - 廣(guang)告服務 - 隱(yin)私聲明 - 版(ban)權申(shen)明 - 免責條(tiao)款 - 幸运pk10官网網站(zhan)地圖 - 網友投稿 - 聯系方式
本站(zhan)內容來自于互聯網,僅供用于網絡技術(shu)學(xue)習(xi),學(xue)習(xi)中(zhong)請(qing)遵循相(xiang)關(guan)法(fa)律法(fa)規
彩乐园官网 | 下一页