王磊 李鑫
摘要:針對嵌入式系統(tǒng)的特點,介紹了幾種在嵌入式系統(tǒng)程序設(shè)計中優(yōu)化C語言代碼的方法,從而提高系統(tǒng)的性能。
關(guān)鍵詞:C程序設(shè)計;程序優(yōu)化;代碼優(yōu)化
中圖分類號:TP311文獻標識碼:A文章編號:1009-3044(2012)01-0192-02
Analysis of the Embedded Program Optimization
WANG Lei, LI Xin
( Xian University of Architecture and Technology, Xian 710055, China)
Abstract: According to the characteristics of embedded system, the paper introduced ways of C language code optimization in embedded system design so as enhance the performance of the system.
Key words: C program design; process optimization; code optimization
隨著數(shù)字信息技術(shù)和網(wǎng)絡(luò)技術(shù)高速發(fā)展嵌入式系統(tǒng)已經(jīng)廣泛滲透到科學(xué)研究領(lǐng)域、各類產(chǎn)業(yè)和商業(yè)文化藝術(shù)以及人們的日常生活中,嵌入式計算機是完成某些特定功能的計算機系統(tǒng),并且軟硬件可裁剪。具有形態(tài)和性能更加小型化,多功能,低功耗等特點,已成為當今計算機技術(shù)發(fā)展的一個重要標志!
程序優(yōu)化是指對解決同一問題的幾個不同的程序,進行比較、修改、調(diào)整或重新編寫程序,把一般程序變換為語句最少、占用內(nèi)存量少、處理速度最快、外部設(shè)備分時使用效率最高的最優(yōu)程序。
1嵌入式程序優(yōu)化遵循的原則
嵌入式程序優(yōu)化主要有以下3個原則:
①等效原則:實現(xiàn)的功能需一致。
②有效原則:使得運行速度快或占用存儲空間小,或兼得。③經(jīng)濟原則:要付出較小的成本。
2嵌入式程序優(yōu)化的主要實施方法
分別為:算法優(yōu)化、編譯優(yōu)化以及代碼優(yōu)化。
2.1算法優(yōu)化
選擇和構(gòu)造適合于問題的算法;(冒泡排序還是快排的選擇問題是這一級早就應(yīng)該完成的)很多經(jīng)典算法都對問題作了一些假設(shè)(包括我們當前已經(jīng)完成的算法實現(xiàn)),而在面對實際問題時我們應(yīng)該重新檢視這些假設(shè),并嘗試不同的思考問題的角度,尋求適合于問題的新算法;發(fā)掘問題的本來意義,從不同的角度思考面對的問題,使用適合于問題的的算法;嘗試打破一些規(guī)則,發(fā)掘和懷疑自己的某些假定,恢復(fù)問題的本來面目。
2.2編譯優(yōu)化
目前很多編譯器都可實現(xiàn)代碼優(yōu)化功能,且提供的代碼也很緊湊。使用編譯器,能得到性能不錯的代碼。然而,機器不能像人類那樣有創(chuàng)造性。所以,我們還需要手工來做一些事情。C語言代碼的優(yōu)化是很難,且很需要技巧的工作。大部分編譯器可以生成為處理器進行過特殊優(yōu)化處理的代碼,如果進行修改,會造成特殊優(yōu)化的破壞導(dǎo)致失效。所以,在決定優(yōu)化代碼之前,一定要測試一下,是自己的代碼更好還是編譯器生成的代碼好。
在嵌入式軟件開發(fā)過程中應(yīng)挑選優(yōu)化能力較強的編譯器,使其發(fā)揮代碼優(yōu)化功能,來生成高效的代碼,提高程序的運行效率。
2.3代碼優(yōu)化
1)變量的處理
編程過程中,解決初始化的問題,最好使用英文單詞的縮寫來代表變量。用縮寫的好處可以加快程序的運行速度并減少占用的內(nèi)存。再一個就是變量類型的選取,選取的范圍越小也可以提高運行速度和降低內(nèi)存的占有,不過算術(shù)運算時容易產(chǎn)生溢出。
函數(shù)調(diào)用越頻繁時,為提高代碼的效率,可以把聲明的局部變量通過編譯器放入寄存器中,而不是放入堆棧。
變量值很大,要使用變量作返回值,會很費時間。使用參數(shù)作為返回值時間上會快些,因為沒有變量返回的復(fù)制時間的問題。但安全性上和函數(shù)重復(fù)使用上差,因為參數(shù)返回破壞了參數(shù)值。最好在編譯時,小的變量用指針返回,小的常量用變量返回,大的常量用參數(shù)或靜態(tài)方法返回。還有就是使用全局變量比函數(shù)傳參數(shù)效率更高,不過要犧牲程序的重入和模塊化,它是因為節(jié)約了參數(shù)入棧和出棧的時間。
2)適當?shù)氖褂煤?/p>
在嵌入式系統(tǒng)中,使用宏代替函數(shù)的方法來滿足性能要求,是在傳遞參數(shù)較多而函數(shù)較短的情況下不錯的選擇。對宏的使用和定義需要謹慎,它可以實現(xiàn)類似函數(shù)的功能,又不像函數(shù)需要調(diào)用返回的好方法,它實質(zhì)上并不是函數(shù),需要考慮到展開后難以預(yù)料的結(jié)果。
如果宏的參數(shù)是復(fù)合結(jié)構(gòu),因為它只是簡單的替換,這里就要考慮操作符的優(yōu)先級問題,單個參數(shù)內(nèi)部各部分之間相互作用的操作符優(yōu)先級低于各個參數(shù)之間的操作符優(yōu)先級,在替換之后,我們需要括號保護宏參數(shù),否則會產(chǎn)生預(yù)想不到的情形。如果宏的參數(shù)是一個函數(shù),展開時會對其參數(shù)多次取值,那么就有可能被調(diào)用多次從而達到不一致的結(jié)果,并有可能產(chǎn)生嚴重錯誤。
3)數(shù)組的處理
(1)數(shù)組在使用前需要對其先初始化。數(shù)組的范圍在初始化時空著不添,在執(zhí)行時將由數(shù)組自動加入,可以提高程序的運行速度。由于事先定義的范圍可能過大,造成存儲的浪費。
(2)大部分情況下,數(shù)組索引用指針運算來替換,可以得到既快又短的代碼。指針運算一般占用空間少,運行速度更快。尤其是使用多維數(shù)組時效果更明顯。
一下是兩段作用相同,效率不同的代碼:
數(shù)組索引指針運算
for(;;){p=array
a=array[s++];for(;;){
……a=*(p++);
……
}}
指針方法的優(yōu)點就是array的地址每次裝入地址p后,每次循環(huán)中,只需對p增量操作。在數(shù)組索引方法中,每次循環(huán)中都必須進行基于s值求數(shù)組下標的復(fù)雜運算。
4)避免使用除法
ARM指令集沒有整數(shù)除法指令,通常除法指令由C語言庫中的函數(shù)執(zhí)行。對于不同的分子和分母,一個32位除法通常需要20至140個時鐘周期,執(zhí)行除法函數(shù)的時間由一個固定時間加上每一位相除的時間。
由于除法操作較費時,所以應(yīng)該避免使用除法。我們知道,除法運算是乘法運算的逆運算,可通過改變表達式,把除法運算改成乘法運算。因為無符號數(shù)除法的速度要高于有符號數(shù)的除法,如果其中有一個是無符號操作數(shù)最好使用無符號除法指令。
5)使用合適的數(shù)據(jù)類型
采用盡可能小的數(shù)據(jù)類型:可以用字符型定義的變量,就不要拿整型來定義,能拿整型定義的就不要拿長整型來定義,能不拿浮點型就不要拿浮點型來定義。當然,一定要防止“溢出”現(xiàn)象,若超過變量的取值范圍后,系統(tǒng)并不會給出“出錯信息”,要靠我們的細心和經(jīng)驗來確保結(jié)果的正確。
在確定表達式是float型和浮點型變量需注意:許多C編譯器把實型常量視為雙精度處理,降低了運算速度換來了更精確的結(jié)果,所以我們最好用“.F”、“.f”為后綴及在函數(shù)聲明時使用float型。使用有符號整型變量時,要考慮是否有必要使用有符號的變量,一些情況下,有符號的運算比較快,但有時卻相反。例如:把整型轉(zhuǎn)化為浮點型時,用大于16位的有符號整型比較快。因為x86構(gòu)架中沒有提供從無符號整型轉(zhuǎn)化到浮點型的指令,因為在整數(shù)運算中需計算商和余數(shù),所以用無符號類型比較快。
6)使用寄存器變量
當一個變量被頻繁讀/寫時,要花費許多存取時間,反復(fù)訪問內(nèi)存??梢允褂肅PU寄存器變量來提高效率,它可以直接進行讀/寫,不需要訪問內(nèi)存。循環(huán)體內(nèi)反復(fù)使用的變量和循環(huán)次數(shù)較多的循環(huán)控制變量都可定義為寄存器變量。靜態(tài)存儲方式的變量都不能定義為寄存器變量,因為寄存器變量屬于動態(tài)存儲方式,所以只有局部自動變量和形參才可以定義為寄存器變量。寄存器變量的說明符是register。下面是一個采用寄存器變量的例子:
register i,sum=0;
for(i=1;i<=n;i++){
sum= sum+i;
…
}
7)If函數(shù)
在條件語句的判別中,先執(zhí)行前面的判別,如果條件不滿足再執(zhí)行后面的判斷。最好將出現(xiàn)可能性最大的條件放在前面。假如x數(shù)值為0-99中的任何一個數(shù),并且概率相同。
if(x>10){ int x=11;}
else if(x<10){ int x=9;}
else (x==10){ int x=10;}
以上程序,當產(chǎn)生的x數(shù)值在10-99之間時(可能性最大),滿足第一個條件后計算機就直接從上述程序中返回而不再執(zhí)行第二和第三個判別了,節(jié)省了運行的時間。
8)Switch語句中根據(jù)發(fā)生頻率來進行case排序
Switch語句是一個普通的編程技術(shù),編譯器會產(chǎn)生if-else-if的嵌套代碼,并按照順序進行比較,發(fā)現(xiàn)匹配時,就跳轉(zhuǎn)到滿足條件的語句執(zhí)行。使用時要留意,每一個測試和跳轉(zhuǎn)只是為了決定下一步要做什么,很浪費處理時間。為提高效率,可以把最可能發(fā)生的情況放在第一位,最不可能的情況放在最后。
9)使用布爾表達式
在C語言中,使用布爾表達式可以用來對變量是否在一定范圍內(nèi)進行檢查。例如布爾表達式x>=min&&x 3結(jié)論 嵌入式程序的性能優(yōu)化與軟件的開發(fā)周期、開發(fā)成本、軟件的可讀性之間通常存在矛盾。在編程時,應(yīng)盡量優(yōu)化自己的程序,減少不必要的運算,如果有多種編程方式可完成同一功能,應(yīng)盡量選擇一種使程序最簡潔,高效的方法。 參考文獻: [1]劉鋒,張曉林.淺析嵌入式程序設(shè)計中的優(yōu)化問題[J].單片機與嵌入式系統(tǒng)應(yīng)用,2006(12). [2]王翠娥.淺析嵌入式C程序設(shè)計的優(yōu)化[J].信息與電腦(理論版),2009(12). [3]劉劍鳴.嵌入式程序設(shè)計中C/C++代碼的優(yōu)化[J].微計算機信息,2003(12). [4]金麗,包志華,陳海進.基于ARM嵌入式系統(tǒng)的C程序優(yōu)化設(shè)計方法[J].南通大學(xué)學(xué)報:自然科學(xué)版,2006(3). [5]曾振河.在ARM實時系統(tǒng)中提高程序執(zhí)行的效率[J].漳州職業(yè)技術(shù)學(xué)院學(xué)報,2008(1). [6]潭浩強.C程序設(shè)計[M].2版.北京:清華大學(xué)出版社,1999. [7]陳波,石旭剛,史故臣.嵌入式C語言在系統(tǒng)開發(fā)中的代碼優(yōu)化[J].計算機時代,2008(11). [8]王軍安.淺析嵌入式系統(tǒng)的軟件優(yōu)化設(shè)計[J].計算機工程與應(yīng)用,2004(3). [9]覃征,王志敏,王向華,等.程序設(shè)計方法與優(yōu)化[M].西安:西安交通大學(xué)出版社,2004.