如何在ARM平臺(tái)上開(kāi)發(fā)低功耗的軟件系統(tǒng)
圖4:緩存的能量?jī)?yōu)勢(shì)
圖4摘自普林斯頓(Brooks,2000)一份論文,顯示了針對(duì)某簡(jiǎn)單應(yīng)用基準(zhǔn)的三套數(shù)據(jù)。針對(duì)不同的緩存大小,這些條塊分別代表性能IP C(單位周期指令數(shù))、功耗和功耗時(shí)間積(ED P)??偟膩?lái)說(shuō),性能會(huì)隨著緩存大小的增加而提升。但是,系統(tǒng)的功耗也會(huì)增加,因?yàn)樵龃缶彺鎲卧獣?huì)相應(yīng)增加功耗。功耗時(shí)間積允許我們?cè)谛阅芎途彺娲笮≈g取得平衡。在這個(gè)例子里,存在一個(gè)最佳點(diǎn),即緩存大小為64k時(shí),此時(shí)的功耗時(shí)間積最小。
最大限度減少數(shù)據(jù)內(nèi)存存取
A RM架構(gòu)的一個(gè)特性是其常量是不確定的,特別是,不可能用單條指令把一個(gè)任意32位常量放到一個(gè)寄存器中。實(shí)際上,所有內(nèi)存存取必須按寄存器中的地址操作,這就意味著程序需要把這些地址和其他常量頻繁地放到寄存器中,而這一點(diǎn)很難做到。解決此問(wèn)題的標(biāo)準(zhǔn)方法是把常量作為文字?jǐn)?shù)據(jù)嵌入到代碼段中,在運(yùn)行時(shí)使用PC相關(guān)的加載進(jìn)行加載。
因此,這種最大限度減少常量影響的方法很實(shí)用。確保在編譯時(shí)這些常量是已知的,如果可能,最好能把這些常量嵌入到單條ARM指令中。為了存取全局變量,盡可能減少加載基址指針的需求。這就需要確保全局變量在運(yùn)行時(shí)都在內(nèi)存中,這樣才能使用單個(gè)指針存取多個(gè)變量。實(shí)現(xiàn)這個(gè)目標(biāo)最簡(jiǎn)單的方式是將全局變量放到一個(gè)結(jié)構(gòu)中。
盡管A R M的堆棧訪(fǎng)問(wèn)相對(duì)高效(堆棧訪(fǎng)問(wèn)可較好地加載和存儲(chǔ)多條指令),但是程序員還可以通過(guò)很多方式來(lái)減少堆棧訪(fǎng)問(wèn):減少活動(dòng)變量、避免占用本地變量地址、可能時(shí)充分利用尾部調(diào)用優(yōu)化、將傳遞到函數(shù)的參數(shù)數(shù)量減少到四個(gè)以下、允許編譯器主動(dòng)內(nèi)聯(lián)函數(shù)等。
遞歸情形和避免遞歸情形的做法更加復(fù)雜。通常編譯器可以對(duì)歸函數(shù)很好地進(jìn)行尾部?jī)?yōu)化。實(shí)際上將所有數(shù)據(jù)存儲(chǔ)到堆棧中可以比其他做法獲得更好的局部性?;蛟S建議可能最好表達(dá)為“除非其他做法讓數(shù)據(jù)局部性更糟或您確信編譯器可以對(duì)遞歸調(diào)用進(jìn)行尾部?jī)?yōu)化,否則不要使用遞歸算法”。應(yīng)編寫(xiě)異常處理程序,增加尾部連鎖的機(jī)會(huì),進(jìn)而避免堆棧環(huán)境內(nèi)不必要的保存和恢復(fù)。
現(xiàn)在我們把注意力轉(zhuǎn)到這個(gè)問(wèn)題的第二頭大象,即指令執(zhí)行。
最大限度減少指令數(shù)目
事實(shí)上,減少指令執(zhí)行次數(shù)本質(zhì)上與性能優(yōu)化是相同的,執(zhí)行的指令數(shù)越少,能耗就越低。另外,還要增加一些明顯的指針。
首先,正確地配置工具。在編譯器和鏈接器完全了解目標(biāo)平臺(tái),甚至無(wú)法實(shí)施一些基本的優(yōu)化。
編寫(xiě)代碼時(shí)要保持敏銳,才能避免不必要的操作。對(duì)于A R M架構(gòu),32位數(shù)據(jù)類(lèi)型是高效的:一般8位和16位數(shù)據(jù)類(lèi)型,盡管占用的存儲(chǔ)空間較少,但是處理效率也較低。在v6和v7架構(gòu)中,打包和接包指令以及S IM D操作一定程序上對(duì)此有些幫助,但是要注意,在主程序中無(wú)法從C訪(fǎng)問(wèn)這些指令。
編寫(xiě)循環(huán)時(shí)要當(dāng)心
可以按照以下一些簡(jiǎn)單的規(guī)則來(lái)編寫(xiě)循環(huán):使用無(wú)符號(hào)的整數(shù)計(jì)數(shù)器,向下倒數(shù),并把是否等于零作為終止條件。這可以讓循環(huán)更短,速度更快,使用的寄存器更少。還要記住,要采用矢量化來(lái)編寫(xiě)循環(huán)。即使在嘗試展開(kāi)和矢量化最簡(jiǎn)單的循環(huán)時(shí),有關(guān)控制結(jié)構(gòu)和數(shù)據(jù)聲明的一些簡(jiǎn)單規(guī)則都可以讓編譯器的作業(yè)變得更簡(jiǎn)單。
圖5:循環(huán)展開(kāi)
圖5顯示了與一個(gè)特定循環(huán)優(yōu)化有關(guān)的一些數(shù)據(jù),這個(gè)循環(huán)優(yōu)化就是循環(huán)展開(kāi)(Brooks,2000)。按照預(yù)期,隨著展開(kāi)因子的增加,執(zhí)行時(shí)間和指令數(shù)目會(huì)減少。我們看到了減少循環(huán)開(kāi)銷(xiāo)和減少地址計(jì)算的效果。功率結(jié)果更加有趣,但不太明顯。因?yàn)轭A(yù)測(cè)器可用來(lái)訓(xùn)練其行為的分支更少且針對(duì)循環(huán)結(jié)束失敗的最終錯(cuò)誤預(yù)測(cè)比例大增,所以隨著循環(huán)進(jìn)一步展開(kāi),分支預(yù)測(cè)器的準(zhǔn)確性出現(xiàn)下降。但是,因?yàn)轫樞蛉≈傅倪B續(xù)數(shù)據(jù)流不經(jīng)常被中斷,所以取指階段的效率可以提升。組合的結(jié)果是減少了每條指令的凈能耗。
因此盡管執(zhí)行時(shí)間基本上低于展開(kāi)因子4,但是因?yàn)楣某掷m(xù)降低,所以所有重要的功耗時(shí)間積也隨之降低。因此有能耗意識(shí)的編譯器或開(kāi)發(fā)人員與只考慮執(zhí)行時(shí)間的編譯器或開(kāi)發(fā)人員相比,會(huì)更傾向于展開(kāi)循環(huán)。
精度滿(mǎn)足需求即可
還必須考慮輸出要求的精度。即使有浮點(diǎn)硬件可用,定點(diǎn)實(shí)現(xiàn)的計(jì)算通常比浮點(diǎn)實(shí)現(xiàn)的計(jì)算更有效率。如果您正在渲染一個(gè)供屏幕查看的圖像,可能并不需要完全符合標(biāo)準(zhǔn),您只需要渲染出可以接受的圖像。
對(duì)標(biāo)準(zhǔn)M P E G- 4解碼函數(shù)進(jìn)行遞進(jìn)優(yōu)化的一項(xiàng)研究(S h i n,2002)已經(jīng)表明,把軟浮點(diǎn)切換為定點(diǎn)二進(jìn)制可以把能耗降低72%。精度損失意味著該結(jié)果不再符合標(biāo)準(zhǔn),但是在所研究的系統(tǒng)上仍然足以滿(mǎn)足渲染用途。
關(guān)于Thumb
T humb指令集專(zhuān)門(mén)設(shè)計(jì)用于改進(jìn)代碼密度,還可以提升窄內(nèi)存系統(tǒng)的性能。但是,在代碼密度確實(shí)改進(jìn)的同時(shí),指令數(shù)也同時(shí)增加了。這是因?yàn)?,與A R M指令相比,減少了個(gè)別Thumb指令的功能。因此Thumb重新編譯會(huì)造成能耗增加,這看起來(lái)是合理的,而我們看到的事實(shí)也的確是這樣。
上述研究表明,如果代碼大小減少4%,指令執(zhí)行數(shù)增加38%,而能耗增加28%。為了找到第三頭大象,我們需要走出處理器及其內(nèi)存的領(lǐng)域,著眼于范圍更大的系統(tǒng)。我們這些天使用的系統(tǒng)已經(jīng)被我們的硬件設(shè)計(jì)同事組合到了一起,這個(gè)系統(tǒng)提供了大量節(jié)能選項(xiàng)。
更廣系統(tǒng)中的節(jié)能
顯而易見(jiàn),沒(méi)有使用的組件應(yīng)盡可能置于低功耗狀態(tài)。這也是所有敏銳的設(shè)計(jì)系統(tǒng)不可分割的組成部分,這些組件應(yīng)包括內(nèi)存和緩存系統(tǒng)、甚至是處理器本身。在多核系統(tǒng)中,我們必須考慮在處理要求相對(duì)低時(shí)中止一個(gè)或多個(gè)內(nèi)核運(yùn)行的可能性。
首先,一個(gè)很小但值得考慮的問(wèn)題是:處理外設(shè)時(shí),要始終嘗試使用中斷機(jī)制,而不是輪詢(xún)機(jī)制。輪詢(xún)循環(huán)只會(huì)耗用能量而無(wú)任何目的。幾乎所有架構(gòu)均包括了某種等待中斷的指令,可以把這種情況下的系統(tǒng)置于待機(jī)狀態(tài)。對(duì)于A R M系統(tǒng),內(nèi)核通常帶有時(shí)鐘門(mén)控,只保留靜態(tài)漏電。
通過(guò)設(shè)計(jì)中斷架構(gòu)來(lái)增加拖尾連鎖,一般可以避免不必要的睡眠喚醒循環(huán)。ARM Cortex-M3架構(gòu)可以自動(dòng)實(shí)現(xiàn)這一點(diǎn)。
評(píng)論