在前文《如何為嵌入式軟件開(kāi)發(fā)選擇編譯器》中講到編譯器對(duì)于嵌入式軟件開(kāi)發(fā)的重要性,以及如何選擇一款優(yōu)秀的編譯器。 文中也比較了現(xiàn)有主流編譯器的編譯優(yōu)化性能,IAR Embedded Workbench編譯器不論在輸出代碼體積還是性能均處于業(yè)界領(lǐng)先地位。
本文中,我們將以IAR Embedded Workbench編譯器為例,闡述如何配置編譯優(yōu)化選項(xiàng),以達(dá)到嵌入式軟件代碼性能和體積的最佳平衡。由于篇幅關(guān)系,本主題將會(huì)分成上、下兩篇。
編譯器代碼構(gòu)建過(guò)程
在介紹如何配置編譯器優(yōu)化選項(xiàng)之前,讓我們先來(lái)了解下編譯器構(gòu)建的過(guò)程。 以IAR Embedded Workbench編譯器為例,其代碼構(gòu)建過(guò)程如下圖。
構(gòu)建過(guò)程分為兩部分:前端和后端。
前端主要將C代碼通過(guò)解析器(Parser)生產(chǎn)中間代碼(Intermediate Code),在這個(gè)過(guò)程中會(huì)介入優(yōu)化器(High-Level Optimizer),其優(yōu)化策略包括函數(shù)內(nèi)聯(lián)(Function in lining), 冗余代碼消除(Dead code elimination), 循環(huán)展開(kāi)(Loop unrolling)等。
后端則將中間代碼通過(guò)目標(biāo)代碼生成器(Code Generator)生成目標(biāo)匯編代碼(Target Code),在這個(gè)過(guò)程中也會(huì)介入優(yōu)化器(Low-Level Optimizer),其優(yōu)化策略包括調(diào)度(Scheduling), 窺視孔(Peephole), 函數(shù)調(diào)用優(yōu)化(Cross call)等。 然后由匯編器(Assembler)將匯編代碼轉(zhuǎn)換成目標(biāo)機(jī)器碼(Object Code)。 最后,通過(guò)鏈接器(Linker),將所有的目標(biāo)機(jī)器碼鏈接成elf格式的可執(zhí)行二進(jìn)制代碼文件。 在鏈接階段也有相應(yīng)的優(yōu)化器(Linker time optimization)進(jìn)行優(yōu)化。
IAR Embedded Workbench
編譯優(yōu)化選項(xiàng)介紹
在IAR Embedded Workbench(基于EWARM v9.32.2)中通過(guò)菜單欄(Project -> Options)打開(kāi)項(xiàng)目選項(xiàng)界面,選中“C/C++ Compiler”欄目,并且在右邊選項(xiàng)卡選中“Optimizations”,即可進(jìn)行編譯優(yōu)化選項(xiàng)配置,如下圖所示。
1. 編譯優(yōu)化等級(jí)配置
如下圖所示,IAR Embedded Workbench共分為4個(gè)優(yōu)化等級(jí)(None, Low, Medium, High),其中等級(jí)“High”又分為3個(gè)子優(yōu)化等級(jí)(Balanced, Size, Speed)。 下表是各個(gè)優(yōu)化等級(jí)對(duì)應(yīng)的優(yōu)化策略總覽。
? 選擇“None”,編譯器只會(huì)進(jìn)行無(wú)用代碼消除等基本優(yōu)化,但編譯速度快,并且最適合C/C++源代碼調(diào)試。
? 最高優(yōu)化等級(jí)除了High(Balanced)之外,也可以選擇High(Size)對(duì)于代碼體積進(jìn)行極致優(yōu)化; 或者選擇High(Speed) ,并且勾選 No size constraints,則對(duì)于代碼性能進(jìn)行極致優(yōu)化。
關(guān)于編譯優(yōu)化微調(diào)項(xiàng)(Enabled transformations)配置方法,我們將在《深入淺出編譯優(yōu)化選項(xiàng)(下)》詳細(xì)介紹,敬請(qǐng)關(guān)注。
2. 多文件編譯(Multi-file Compilation)
通常情況下,編譯器逐個(gè)編譯C/C++源文件。 編譯器的單次編譯視野僅限于當(dāng)前C/C++源文件,不能獲知其他源文件的情況,包括全局變量,函數(shù)調(diào)用,指針別名等關(guān)系。 因此編譯器會(huì)采用較為保守和安全的優(yōu)化假設(shè)。
IAR Embedded Workbench則為用戶提供了 **“多文件編譯” **功能,如下圖。 編譯器在工程全局級(jí)別或者文件組級(jí)別,允許一次編譯多個(gè)文件,從而增加了編譯視野,可以進(jìn)行更為深度的編譯優(yōu)化策略實(shí)施,通常能獲得更好的編譯優(yōu)化效果。
3. 靈活配置編譯優(yōu)化選項(xiàng)作用域
IAR Embedded Workbench提供了不同作用域的編譯優(yōu)化選項(xiàng)設(shè)置,使用戶能夠更加靈活的進(jìn)行配置,對(duì)不同編譯優(yōu)化需求的代碼進(jìn)行分別配置。
? 全局設(shè)置:如之前介紹的編譯優(yōu)化選項(xiàng)設(shè)置方法均為全局設(shè)置,作用于整個(gè)工程范圍。
? 每個(gè)文件/每個(gè)組的設(shè)置:當(dāng)文件/組中的所有函數(shù)必須具有與項(xiàng)目不同的編譯優(yōu)化設(shè)置時(shí),打開(kāi)文件/組編譯選項(xiàng)界面(在項(xiàng)目管理器選中文件/組,右擊鼠標(biāo)選擇Options),選擇“Override inherited settings”,如下圖。 然后進(jìn)行編譯優(yōu)化設(shè)置。
? 單個(gè)函數(shù):當(dāng)某些函數(shù)必須具有不同的編譯優(yōu)化設(shè)置時(shí),可以在源代碼中使用 #pragma 關(guān)鍵字進(jìn)行單獨(dú)配置,如下例。
4. 鏈接階段優(yōu)化選項(xiàng)
IAR Embedded Workbench在鏈接階段也提供了相應(yīng)的代碼優(yōu)化選項(xiàng),如下圖。
? 鏈接階段默認(rèn)消除未使用的變量和函數(shù)。
? 小函數(shù)內(nèi)聯(lián)(inline small routines):將對(duì)小函數(shù)的某些調(diào)用替換為函數(shù)的本體。
? 合并重復(fù)段(Merge duplicate sections):鏈接器可以檢測(cè)具有相同內(nèi)容的只讀段,并僅保留每個(gè)此類段的一個(gè)副本,從而將對(duì)任何重復(fù)段的所有引用重定向到保留的段。
? C++虛擬函數(shù)消除(Perform C++ virtual function elimination):虛函數(shù)是 C++ 中的一種特殊函數(shù),它的實(shí)際調(diào)用取決于對(duì)象的實(shí)際類型。 虛函數(shù)的調(diào)用需要運(yùn)行時(shí)動(dòng)態(tài)解析,因此會(huì)導(dǎo)致一定的運(yùn)行時(shí)開(kāi)銷。 “C++虛擬函數(shù)消除” 可刪除不需要的虛擬函數(shù)和動(dòng)態(tài)運(yùn)行時(shí)類型信息,以減少程序運(yùn)行時(shí)的開(kāi)銷,提高程序的性能。
嵌入式軟件編譯優(yōu)化選項(xiàng)配置整體思路
嵌入式系統(tǒng)中通常硬件資源有限,特別是存儲(chǔ)器容量,直接與MCU硬件成本掛鉤,影響整個(gè)系統(tǒng)的硬件物料成本; 另一方面,嵌入式軟件又需要對(duì)外部信號(hào)進(jìn)行實(shí)時(shí)響應(yīng),對(duì)外部設(shè)備進(jìn)行實(shí)時(shí)控制,比如馬達(dá)控制組件; 除此之外,電池供電的嵌入式設(shè)備需要具備低功耗特性,要求CPU盡可能處于深度睡眠狀態(tài),以盡可能延長(zhǎng)設(shè)備的單次電池工作時(shí)間。 結(jié)合上述情況,對(duì)于嵌入式軟件進(jìn)行編譯優(yōu)化選項(xiàng)配置需要進(jìn)行差異化考量,具體如下:
? 對(duì)于整個(gè)嵌入式軟件項(xiàng)目作用域,可以考慮極致代碼體積優(yōu)化。 較少的代碼體積可以適配較小flash容量的MCU,從而節(jié)省硬件物料成本。
? 對(duì)于運(yùn)行頻度很高的代碼段,可以考慮極致代碼性能優(yōu)化。 這樣可以使得關(guān)鍵代碼在相同CPU速度的情況下,達(dá)到更高的實(shí)時(shí)響應(yīng)速度。
? 另外,在電池供電的低功耗應(yīng)用中,CPU一般處在深度睡眠狀態(tài)。 通常是間隔一段時(shí)間或者外部事件到來(lái),喚醒CPU執(zhí)行一個(gè)任務(wù),然后CPU重新回到深度睡眠狀態(tài)。 設(shè)備功耗等于CPU深度睡眠的靜態(tài)功耗和任務(wù)運(yùn)行的動(dòng)態(tài)功耗之和。 根據(jù)MCU硬件電氣特性,其單位時(shí)間動(dòng)態(tài)功耗(mA級(jí)別)要遠(yuǎn)大于單位時(shí)間靜態(tài)功耗(uA級(jí)別)。
對(duì)于經(jīng)常需要喚醒執(zhí)行的軟件任務(wù),可以考慮極致代碼性能優(yōu)化。 這樣會(huì)減少動(dòng)態(tài)功耗的時(shí)間,以達(dá)到整體功耗的下降,從而增加設(shè)備的電池使用壽命。
注意事項(xiàng):
? #pragma optimize 只能降低對(duì)應(yīng)函數(shù)的優(yōu)化等級(jí),或者選擇另外一種優(yōu)化策略。 如果 pragma optimize的優(yōu)化等級(jí)比編譯器選項(xiàng)的優(yōu)化等級(jí)高,那么 pragma optimize命令會(huì)被忽略。
? 高優(yōu)化等級(jí)會(huì)讓編譯時(shí)間變長(zhǎng),同時(shí)讓調(diào)試變得困難一些(因?yàn)楦邇?yōu)化等級(jí)會(huì)讓生成的代碼和源代碼的對(duì)應(yīng)關(guān)系沒(méi)有那么直接)。 如果在調(diào)試過(guò)程中發(fā)現(xiàn)類似的問(wèn)題,建議降低優(yōu)化等級(jí)進(jìn)行調(diào)試。
總結(jié)
IAR Embedded Workbench是一款業(yè)界領(lǐng)先的編譯工具鏈,除了提供卓越的性能之外,還提供了豐富靈活的編譯優(yōu)化選項(xiàng)配置,以幫助用戶在不同的嵌入式應(yīng)用需求下,都能找到最佳的嵌入式軟件代碼性能和體積的平衡點(diǎn)。
在下一篇《深入淺出編譯優(yōu)化選項(xiàng)(下)》中,我們將介紹編譯過(guò)程中的優(yōu)化策略以及如何在IAR Embedded Workbench配置編譯優(yōu)化微調(diào)項(xiàng)(Enabled transformations),讓用戶可以根據(jù)代碼需求配置出更加精準(zhǔn)的編譯優(yōu)化策略組合。
審核編輯:湯梓紅
-
嵌入式
+關(guān)注
關(guān)注
5082文章
19126瀏覽量
305197 -
IAR
+關(guān)注
關(guān)注
5文章
352瀏覽量
36681 -
優(yōu)化
+關(guān)注
關(guān)注
0文章
220瀏覽量
23906 -
代碼
+關(guān)注
關(guān)注
30文章
4788瀏覽量
68612 -
編譯器
+關(guān)注
關(guān)注
1文章
1634瀏覽量
49132
原文標(biāo)題:深入淺出編譯優(yōu)化選項(xiàng)(上)
文章出處:【微信號(hào):IAR愛(ài)亞系統(tǒng),微信公眾號(hào):IAR愛(ài)亞系統(tǒng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論