?? c6000軟件優化經驗總結(3).htm
字號:
L_tmp = Mac_32 (L_32, hi1, lo1, hi2, lo2);</P>
<P>2、改編代碼:</P>
<P> L_tmp = _sadd(_sadd(_smpyh(hl1_32, hl2_32),</P>
<P> ((_mpyhslu(hl1_32,
hl2_32)>>16)<<1)+</P>
<P> ((_mpyhslu(hl2_32,
hl1_32)>>16)<<1)), L_32);</P>
<P>3、優化方法說明:</P>
<P> 兩個32位的數相乘,不必分成四個16位的數相乘,直接用32位相乘。其中:</P>
<P> hl1_32 = hi1<<16 +
lo1<<1, hl2_32 = hi2
<<16 + lo2 <<1 。</P>
<P>源代碼實現: L_32 = L_32 + (hi1*hi2)<<1 + ( (hi1*lo2)>>15 +
(lo1*hi2)>>15 )<<1</P>
<P>4、技巧:</P>
<P>低16位與高16位相乘時,低16位使用的是無符號數。</P>
<P>十五、16位除法的優化</P>
<P>1、源代碼:</P>
<P>Word16 div_s (Word16 var1, Word16 var2) //實現
var1/var2</P>
<P>{</P>
<P> Word16 var_out = 0;</P>
<P> Word16 iteration;</P>
<P> Word32 L_num = (Word32)var1;</P>
<P> Word32 L_denom = (Word32)var2;</P>
<P>
for (iteration = 0; iteration < 15; iteration++)</P>
<P>
{</P>
<P>
var_out <<= 1;</P>
<P>
L_num <<= 1;</P>
<P>
if (L_num >= L_denom)</P>
<P>
{</P>
<P>
L_num = L_sub (L_num, L_denom);</P>
<P>
var_out = add (var_out, 1);</P>
<P>
}</P>
<P>
}</P>
<P> return (var_out);</P>
<P>}</P>
<P>2、改編代碼:</P>
<P>Word16 div_s1 (Word16 var1, Word16 var2)</P>
<P>{</P>
<P> Word32 var1int;</P>
<P> Word32 var2int;</P>
<P> var1int = var1 << 16;</P>
<P> var2int = var2 << 15;</P>
<P> var1int = _subc(var1int,var2int);</P>
<P> var1int = _subc(var1int,var2int);</P>
<P> var1int = _subc(var1int,var2int);</P>
<P> var1int = _subc(var1int,var2int);</P>
<P> var1int = _subc(var1int,var2int);</P>
<P> var1int = _subc(var1int,var2int);</P>
<P> var1int = _subc(var1int,var2int);</P>
<P> var1int = _subc(var1int,var2int);</P>
<P> var1int = _subc(var1int,var2int);</P>
<P> var1int = _subc(var1int,var2int);</P>
<P> var1int = _subc(var1int,var2int);</P>
<P> var1int = _subc(var1int,var2int);</P>
<P> var1int = _subc(var1int,var2int);</P>
<P> var1int = _subc(var1int,var2int);</P>
<P> var1int = _subc(var1int,var2int);</P>
<P> return (var1int & 0xffff);</P>
<P>}</P>
<P>3、優化方法說明:</P>
<P>實現16位的除法,要求被除數var1和除數var2都是整數,且var1<=var2。利用C6XX特有的指令subc,實現除法的循環移位相減操作。</P>
<P>4、技巧:</P>
<P>把被除數和除數都轉換成32位數來操作,返回時取低16位數。</P>
<P>十六、C6X優化inline舉例:</P>
<P>1、原程序:</P>
<P> for (i = LO_CHAN; i <= HI_CHAN; i++)</P>
<P> {</P>
<P> </P>
<P> norm_shift = norm_l(st->ch_noise[i]);</P>
<P> Ltmp = L_shl(st->ch_noise[i], norm_shift);</P>
<P> </P>
<P> norm_shift1 = norm_l(st->ch_enrg[i]);</P>
<P> Ltmp3 = L_shl1(st->ch_enrg[i], norm_shift1 -
1);</P>
<P> Ltmp2 = L_divide(Ltmp3, Ltmp);</P>
<P> Ltmp2 = L_shr(Ltmp2, 27 - 1 + norm_shift1 -
norm_shift); // * scaled as 27,4 *</P>
<P> if (Ltmp2 == 0)</P>
<P> Ltmp2 = 1;</P>
<P> </P>
<P> Ltmp1 = fnLog10(Ltmp2);</P>
<P> Ltmp3 = L_add(Ltmp1, LOG_OFFSET - 80807124); //
* -round(log10(2^4)*2^26 *</P>
<P> Ltmp2 = L_mult(TEN_S5_10, extract_h(Ltmp3));</P>
<P> if (Ltmp2 < 0)</P>
<P> Ltmp2 = 0;</P>
<P> // * 0.1875 scaled as 10,21 *</P>
<P> Ltmp1 = L_add(Ltmp2, CONST_0_1875_S10_21);</P>
<P> // * tmp / 0.375 2.667 scaled as 5,10, Ltmp is
scaled 15,16 *</P>
<P> Ltmp = L_mult(extract_h(Ltmp1),
CONST_2_667_S5_10);</P>
<P> ch_snr[i] = extract_h(Ltmp);</P>
<P> }</P>
<P> */</P>
<P> </P>
<P>2、優化后程序:</P>
<P> //因循環體太大,拆成兩個循環并把相應的函數內嵌以使程序能pipeline,</P>
<P> //用L_div_tmp[]保存因拆分而產生的中間變量。</P>
<P> for (i = LO_CHAN; i <= HI_CHAN; i++)</P>
<P> {</P>
<P> //norm_shift = norm_l(st->ch_noise[i]);</P>
<P> norm_shift = _norm(st->ch_noise[i]);</P>
<P> Ltmp = _sshl(st->ch_noise[i], norm_shift);</P>
<P> </P>
<P> //norm_shift1 = norm_l(st->ch_enrg[i]); </P>
<P> norm_shift1 =
_norm(st->ch_enrg[i]); </P>
<P> //Ltmp3 = L_shl1(st->ch_enrg[i], norm_shift1 -
1);</P>
<P> LLtmp1 = st->ch_enrg[i]; </P>
<P> LLtmp1 = LLtmp1 << (norm_shift1 + 7);</P>
<P> Ltmp3 = (Word32)(LLtmp1 >> 8);</P>
<P> </P>
<P> Ltmp2 = IL_divide(Ltmp3, Ltmp);</P>
<P> //Ltmp2 = L_shr(Ltmp2, 27 - 1 + norm_shift1 -
norm_shift); </P>
<P> Ltmp2 = (Ltmp2 >> (27 - 1 + norm_shift1 -
norm_shift));</P>
<P> </P>
<P> if (Ltmp2 == 0)</P>
<P> Ltmp2 = 1;</P>
<P> L_div_tmp[i] = Ltmp2;</P>
<P> }</P>
<P> for (i = LO_CHAN; i <= HI_CHAN; i++)</P>
<P> {</P>
<P> Ltmp2 = L_div_tmp[i];</P>
<P> Ltmp1 = IfnLog10(Ltmp2);</P>
<P> //Ltmp3 = L_add(Ltmp1, LOG_OFFSET -
80807124); </P>
<P> Ltmp3 = _sadd(Ltmp1, LOG_OFFSET - 80807124);</P>
<P> //Ltmp2 = L_mult(TEN_S5_10, extract_h(Ltmp3));</P>
<P> Ltmp2 = _smpy(TEN_S5_10, (Ltmp3 >> 16));</P>
<P> if (Ltmp2 < 0)</P>
<P> Ltmp2 = 0;</P>
<P> </P>
<P> Ltmp1 = _sadd(Ltmp2, CONST_0_1875_S10_21);</P>
<P> </P>
<P> //Ltmp = L_mult(extract_h(Ltmp1),
CONST_2_667_S5_10);</P>
<P> Ltmp = _smpy((Ltmp1 >> 16),
CONST_2_667_S5_10); </P>
<P> //ch_snr[i] = extract_h(Ltmp);</P>
<P> ch_snr[i] = (Ltmp >> 16);</P>
<P> }</P>
<P> </P>
<P>3、優化說明</P>
<P> 觀察上面這個循環,循環體本身比較大,且含有兩個函數L_divide()和</P>
<P> fnLog10(),而C62內部只有32個寄存器,且有些寄存器是系統用的,如B14、B15這樣循環體太大將會導致寄存器不夠分配,從而導致系統編譯器無法實現循環的pipeline。</P>
<P> 為了實現循環的pipeline。我們需要把循環體進行拆分,拆分時要考慮以下幾點:</P>
<P> (1)、拆分成幾個循環比較合適?在各個循環能pipeline的前提下,拆開的循環個數越少越好。這就要求盡可能讓各個循環的運算量接近。</P>
<P> (2)考慮在什么地方把程序拆開比較合適?循環體里的數據流往往并不是單一的,在拆開的斷點處勢必要用中間變量保存上次的循環運算結果,供以后的循環用。適當的拆開循環體,使所需的中間變量越少越好。</P>
<P> (3)循環體中的函數調用必須定義成內嵌形式,含有函數調用的循環系統是無法使之pipeline的;各個循環體中的判斷分支機構不可太多,否則系統也無法使之pipeline,為此應近可能把可以確定下來的分支確定下來,并盡可能用內嵌指令。 </P>
<P> 針對上面這個例子,考慮:</P>
<P> (1)為讓各個循環的運算量大致相當,應把L_divide()和fnLog10()分到兩個循環中去,從循環體大小上考慮,估計拆成兩個循環比較合適。</P>
<P> (2)考慮在什么地方把程序拆開比較合適?在</P>
<P> if (Ltmp2 == 0)</P>
<P> Ltmp2 = 1;</P>
<P>后拆開,因為后面用到的數據只有Ltmp2,故只需用一個數組保存每次循環的Ltmp2值即可。</P>
<P> (3)循環體中的兩處函數調用L_divide()和fnLog10()都定義了其內嵌形式,IL_divide()和IfnLog10()。當把可以確定下來的分支作確定處理,并盡可能用內嵌指令后,該循環體中所剩的分支結構已很少,循環體可以pipeline。優化前程序用2676
cycle,優化后用400
cycle。優化后兩個子循環的MII分別為14和6cycle。</P><BR></TD></TR></TBODY></TABLE><BR>
<TABLE class=hight1 cellSpacing=0 cellPadding=0 width="100%"
bgColor=#cccccc border=0>
<TBODY>
<TR>
<TD> </TD></TR></TBODY></TABLE><BR>
<TABLE
style="BORDER-RIGHT: #cccccc 1px solid; BORDER-TOP: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; BORDER-BOTTOM: #cccccc 1px solid"
height=29 cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR bgColor=#ffa45b>
<TD class=hight2> </TD></TR>
<TR bgColor=#ff7300>
<TD class=font13 style="PADDING-LEFT: 10px" height=20><IMG
src="C6000軟件優化經驗總結(3).files/icon06.gif" align=absMiddle> <FONT
color=#ffffff><STRONG>相關文章</STRONG></FONT></TD></TR>
<TR bgColor=#f29800>
<TD class=hight2> </TD></TR>
<TR>
<TD style="PADDING-LEFT: 10px; LINE-HEIGHT: 24px">· <A class=link13
title="文章標題:TMS320VC5509的工作流程 作 者:佚名 更新時間:2006-2-22 15:30:34 點擊次數:90"
href="http://www.icembed.com/info.asp?ArticleID=1421">TMS320VC5509的工作流程</A>[<FONT
color=red>90</FONT>]<BR>· <A class=link13
title="文章標題:TI-MSP430F149在TCP/IP上的擴展 作 者:佚名 更新時間:2006-2-22 15:25:00 點擊次數:95"
href="http://www.icembed.com/info.asp?ArticleID=1419">TI-MSP430F149在TCP/IP上的擴展</A>[<FONT
color=red>95</FONT>]<BR>· <A class=link13
title="文章標題:AVR芯片的ISP全攻略 作 者:佚名 更新時間:2006-2-22 15:22:52 點擊次數:67"
href="http://www.icembed.com/info.asp?ArticleID=1418">AVR芯片的ISP全攻略</A>[<FONT
color=red>67</FONT>]<BR>· <A class=link13
title="文章標題:pci卡設計心得 作 者:佚名 更新時間:2006-2-22 15:18:04 點擊次數:81"
href="http://www.icembed.com/info.asp?ArticleID=1416">pci卡設計心得</A>[<FONT
color=red>81</FONT>]<BR>· <A class=link13
title="文章標題:C6000軟件優化經驗總結(2) 作 者:佚名 更新時間:2006-2-22 15:09:16 點擊次數:83"
href="http://www.icembed.com/info.asp?ArticleID=1412">C6000軟件優化經驗總結(2)</A>[<FONT
color=red>83</FONT>]<BR></TD></TR></TBODY></TABLE><BR>
<TABLE
style="BORDER-RIGHT: #cccccc 1px solid; BORDER-TOP: #cccccc 1px solid; BORDER-LEFT: #cccccc 1px solid; BORDER-BOTTOM: #cccccc 1px solid"
cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR bgColor=#ffa45b>
<TD class=hight2> </TD></TR>
<TR bgColor=#ff7300>
<TD class=font13 style="PADDING-LEFT: 10px" height=20><IMG
src="C6000軟件優化經驗總結(3).files/icon06.gif" align=absMiddle> <FONT
color=#ffffff><STRONG>文章評論</STRONG></FONT></TD></TR>
<TR bgColor=#f29800>
<TD class=hight2> </TD></TR>
<TR>
<TD
style="PADDING-RIGHT: 10px; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; LINE-HEIGHT: 24px; PADDING-TOP: 10px"> 沒有任何評論
</TD></TR></TBODY></TABLE><BR>(*只顯示最新10條評論。評論內容只代表網友觀點,與本站立場無關。) <BR><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -