https://blog.csdn.net/favory/article/details/4706428算法
嵌入式系統因爲受功耗、成本和體積等因素的制約,嵌入式微處理器的處理能力與桌面系統處理器相比也存在較大差距,故嵌入式系統對程序運行的空間和時間要求更爲苛刻。一般,須要對嵌入式應用程序進行性能優化,以知足嵌入式應用的性能需求。編程
1 嵌入式程序優化的類型小程序
嵌入式應用程序優化,指在不改變程序功能的狀況下,經過修改原來程序的算法、結構,並利用軟件開發工具對程序進行改進,使修改後的程序運行速度更高或代碼尺寸更小。數組
按照優化的側重點不一樣,程序優化可分爲運行速度優化和代碼尺寸優化。運行速度優化是指在充分掌握軟硬件特性的基礎上,經過應用程序結構調整等手段來縮短完成指定任務所需的運行時間;代碼尺寸優化則是指應用程序在可以正確實現所需功能的前提下,儘量減少程序的代碼量。實際應用中,這二者每每是相互矛盾的,爲了提升程序運行速度,就要以增長代碼量爲代價;而爲了減少程序代碼尺寸,可能又要以下降程序運行速度爲代價。所以,在對程序進行優化以前,應根據實際須要來制定具體的優化策略。隨着計算機和微電子技術的不斷髮展,存儲空間已再也不是制約嵌入式系統的主要因素,所以本文主要討論運行速度優化。緩存
2 嵌入式程序優化遵循的原則
嵌入式程序優化主要遵循如下3個原則。
①等效原則:優化先後程序實現的功能一致。
②有效原則:優化後要比優化前運行速度快或佔用存儲空間小,或兩者兼有。
③經濟原則:優化程序要付出較小的代價,取得較好的結果。性能優化
3 嵌入式程序優化的主要方面數據結構
嵌入式程序的優化分爲3個方面:算法和數據結構優化、編譯優化以及代碼優化。異步
3.1 算法和數據結構優化函數
算法和數據結構是程序設計的核心所在,算法的好壞在很大程度上決定了程序的優劣。爲了實現某種功能,一般能夠採用多種算法,不一樣算法的複雜度和效率差異很大。選擇一種高效的算法或對算法進行優化,可使應用程序得到更高的優化性能。例如:在數據搜索時,二分查找法要比順序查找法快。遞歸程序須要大量的過程調用,並在堆棧中保存全部返回過程的局部變量,時間效率和空間效率都很是低;若根據實際狀況對遞歸程序採用迭代、堆棧等方法進行非遞歸轉換,則可大幅度提升程序的性能。工具
數據結構在程序的設計中也佔有重要的地位。例如:若是在一些無序的數據中屢次進行插入、刪除數據項操做,那麼採用鏈表結構就會比較快。
算法和數據結構優化是首選的優化技術。
3.2 編譯優化
如今,不少的編譯器都具備必定的代碼優化功能。在編譯時,借用並行程序設計技術,進行相關性分析;得到源程序的語義信息,採用軟件流水線、數據規劃、循環重構等技術,自動進行一些與處理器體系無關的優化,生成高質量的代碼。許多編譯器有不一樣級別的優化選項,能夠選用一種合適的優化方式。一般狀況下,若是選用了最高級別的優化方式,那麼編譯器將片面追求代碼的優化,有時會致使錯誤。
另外,還有一些專用的編譯器針對某些體系結構進行了優化設計,能夠充分利用硬件資源來生成高質量的代碼。例如:Microsoft eMbedded Visual C++版的Intel編譯器徹底針對Intel XScale體系,通過高度優化,能建立運行速度更快的代碼。此編譯器採用了多種優化技術,包括優化指令管道操做的調度技術、雙重加載與存儲Intel XScale技術功能支持以及過程間優化(將函數使用的變量存放到寄存器,以便快速訪問)等。
在嵌入式軟件開發過程當中應選擇一種優化能力強的編譯器,充分利用其代碼優化功能,生成高效的代碼,提升程序的運行效率。
3.3 代碼優化
代碼優化,就是採用彙編語言或更精簡的程序代碼來代替原有的代碼,使編譯後的程序運行效率更高。編譯器能夠自動完成程序段和代碼塊範圍內的優化,但很難獲取程序語義信息、算法流程和程序運行狀態信息,於是須要編程人員進行手工優化。如下是一些經常使用的優化技術和技巧。
(1)代碼替換
使用週期短的指令代替週期長的指令,以下降運算的強度。
①減小除法運算。用關係運算符兩邊乘除數避免除法操做,還有一些除法和取模的運算能夠用位操做來代替。由於位操做指令只需一個指令週期,而「/」運算則須要調用子程序,代碼長,執行慢。例如:
優化前if((a/b)>c)和a=a/4
優化後if(a>(b*c))和a=a>>2
②減小乘方運算。例如:
優化前a=pow(a,3.0)
優化後a=a*a*a
③使用白加、自減指令。例如:
優化前a=a+一、a=a-l
優化後a++、a--或inc、dec
④儘可能使用小的數據類型。在所定義的變量知足使用要求的條件下,優先使用順序爲:字符型(char)>整型(im)>長整型(long int)>浮點型(float)。
對除法來講,使用無符號數比有符號數會有更高的效率。在實際調用中,儘可能減小數據類型的強制轉換;少用浮點運算,若是運算的結果可以控制在偏差以內,則可用長整型代替浮點型。
(2)全局變量與局部變量
少用全局變量,多用局部變量。全局變量是放在數據存儲器中的,定義了全局變量,MCU就少了一個能夠利用的數據存儲器空間,太多的全局變量,會致使編譯器無足夠的內存分配;而局部變量則大多定位於MCU內部的寄存器中。在絕大多數的MCU中,使用寄存器的操做速度比數據存儲器快,指令也更靈活,有利於生成質量更高的代碼,並且局部變量所佔用的寄存器和數據存儲器在不一樣的模塊中能夠重複利用。
(3)使用寄存器變量
當一個變量被頻繁讀/寫時,須要反覆訪問內存,花費大量的存取時間。爲了提升訪問效率,可使用CPU寄存器變量,不須要訪問內存,直接進行讀/寫。循環次數較多的循環控制變量及循環體內反覆使用的變量都可定義爲寄存器變量,而循環計數是應用寄存器變量的最佳選擇。只有局部自動變量和形參才能夠定義爲寄存器變量。由於寄存器變量屬於動態存儲方式,所以凡須要採用靜態存儲方式的變量都不能定義爲寄存器變量。寄存器變量的說明符是register。下面是一個採用寄存器變量的例子:
register i,sum=0;
for(i=1;i<=n;i++)
{
sum=sum+i;
...
}
(4)減小或避免執行耗時的操做
應用程序的大量運行時問一般花費在關鍵程序模塊,關鍵模塊每每包含循環或嵌套循環。減小循環中耗時的操做,能夠提升程序的執行速度。常見的耗時操做有:輸入/輸出操做、文件訪問、圖形界面操做和系統調用等。其中,若是沒法避免文件的讀/寫,那麼對文件的訪問將是影響程序運行速度的一大因素。提升文件訪問速度的方法有兩種:一種是採用內存映射文件;另外一種是使用內存緩存。
(5)switch語句用法的優化
編程時,對case值按照可能性排序,將最可能發生的狀況放在第一個,最不可能的狀況放在最後一個,能夠提升switch語句塊的執行速度。
(6)循環體的優化
循環體是程序設計和優化的重點,對於一些不須要循環變量參加運算的模塊,能夠把它放到循環的外面。對於次數固定的循環體,for循環比while循環效率更高,減計數循環比增計數循環速度快。例如:
優化前:
for(i=0;i<100;i++)
{
sum=sum+100;
...
}
優化後:
for(i=100;i!=0;i--)
{
sum=sum+100;
...
}
實際運行時,每次循環須要在循環體外加兩條指令:一條減法指令(減小循環計數值)和一條條件分支指令。這些指令稱爲「循環開銷」。在ARM處理器上,減法指令須要1個週期,條件分支指令須要3個週期,這樣每一個循環另加了4個週期的開銷。能夠採用循環展開的方法來提升循環運行的速度,即:重複循環主題屢次,並按一樣的比例減小循環次數來減少循環的開銷,以增長代碼尺寸。來換取程序的運行速度。。
(7)函數調用
高效的調用函數,儘可能限制使用函數的參數個數,不要超過4個。ARM調用時,4個如下的形參經過寄存器傳遞,第5個以上的形參經過存儲器棧傳遞。若是有更多的參數調用,則可將相關的參數組織在一個結構體內,用傳遞結構體指針來代替參數。
(8)內聯函數和內嵌彙編
對性能影響大的重要函數可使用關鍵字_inline內聯,會省去調用函數的開銷,負面影響是增長了代碼尺寸。程序中對時間要求苛刻的部分能夠用內嵌彙編來編寫,一般能夠帶來速度上的顯著提升。
(9)查表代替計算
在程序中儘可能不進行很是複雜的運算,如浮點數的開方。對於這些消耗時間和資源的運算,能夠採用空間換取時間的方法。預先將函數值計算出來,置於程序存儲區中,之後程序運行時直接查表便可,減少了程序執行過程當中重複計算的工做量。
(10)使用針對硬件優化的函數庫
Intel公司爲XScale處理器設計的GPP(Graphics Performance Primitives library)/IPP(Integrated Perform-ance Primitives library)庫,針對多媒體處理、圖形處理和數值運算的一些典型操做和算法進行了手工優化,能夠很好地發揮XScale硬件的計算潛能,達到很高的執行效率。
(11)利用硬件特性
爲了提升程序的運行效率,要充分利用硬件特性來減少其運行開銷,例如減小中斷次數、利用DMA傳輸方式等。
CPU對各類存儲器的訪問速度排序依次爲:CPU內部RAM>外部同步RAM>外部異步RAM>Flash/ROM。對於已經燒錄在Flash或ROM中的程序代碼,若是讓CPU直接從中讀取代碼執行,運行速度較慢,則可在系統啓動後將Flash或ROM中的目標代碼拷貝至RAM中後執行,以提升程序的運行速度。
4 結論
嵌入式程序的性能優化與軟件的開發週期、開發成本、軟件的可讀性之聞一般存在矛盾。要權衡利弊,做出折中的選擇。將算法和數據結構優化做爲首選優化技術;而後根據功能、性能差別和投資預算等因素選擇高效的編譯器、系統運行庫和圖形庫;使用性能監測工具偵測佔主要運行時間的程序熱點,採用代碼優化手段對其進行優化;最後使用高效的編譯器進行編譯優化,從而獲得高質量的代碼。