H.264在ADSP-BF561上的實(shí)現(xiàn)與優(yōu)化
2.2.2.3 代碼層次優(yōu)化
針對(duì)ADSP-BF561平臺(tái),代碼層次的優(yōu)化工作包括以下幾個(gè)方面:
(1)內(nèi)聯(lián)函數(shù)。將經(jīng)常調(diào)用的函數(shù)體較小的函數(shù)改為內(nèi)聯(lián)。編譯條件中有關(guān)于內(nèi)聯(lián)函數(shù)優(yōu)化的選項(xiàng)。內(nèi)聯(lián)函數(shù)的使用是將代碼的大小和運(yùn)行效率取一個(gè)折中。根據(jù)實(shí)際情況,代碼的大小并非限制條件,所以應(yīng)盡可能多地使用內(nèi)聯(lián)函數(shù)。在項(xiàng)目配置中選中when declared inline選項(xiàng)。
(2)跳轉(zhuǎn)預(yù)測(cè)。ADSP-BF561采用了靜態(tài)預(yù)測(cè)的方式來(lái)預(yù)測(cè)有條件判斷情況,預(yù)測(cè)不成功會(huì)造成4~8個(gè)內(nèi)核時(shí)鐘(CCLK)的延誤。如果事先知道某些跳轉(zhuǎn)的概率,將可能性最大的分支放在最前面,可以從概率上降低預(yù)測(cè)不成功而造成的stall。
(3)使用硬件支持循環(huán)。對(duì)于大部分平臺(tái),將一些循環(huán)體小的循環(huán)展開也能提高效率。ADSP-BF561有兩組硬件計(jì)數(shù)器用以支持循環(huán)。所以除非是展開三層以上的循環(huán),否則,展開循環(huán)體不能提高效率。
(4)內(nèi)存。嵌入式系統(tǒng)的內(nèi)存是非常寶貴的資源。避免頻繁的動(dòng)態(tài)申請(qǐng)和釋放內(nèi)存,能減少碎片產(chǎn)生,提高內(nèi)存的利用率。X264工程也不會(huì)頻繁地申請(qǐng)釋放內(nèi)存。在項(xiàng)目中,具體做法是編寫平臺(tái)相關(guān)的malloc和free函數(shù)。將經(jīng)常使用的中間數(shù)據(jù)在L1數(shù)據(jù)空間中分配。
(5)注釋不需要代碼。去掉代碼中不需要的部分,主要會(huì)去掉CAVLC以及部分碼率控制、csp、cpu、信息統(tǒng)計(jì)、調(diào)試和psnr計(jì)算等部分代碼,這樣做的目的是為了減小文件大小和去除代碼中的一些跳轉(zhuǎn)。不建議刪除代碼,可以使用注釋符或用宏切換的方式,以防止以后參數(shù)改變時(shí)需要使用未使用過(guò)的代碼。
2.2.2.4 平臺(tái)層次優(yōu)化
ADSP-BF561相應(yīng)的編程參考和硬件參考對(duì)其平臺(tái)特性有詳細(xì)介紹。一些平臺(tái)自帶的優(yōu)化功能,如CACHE的開啟和配置等不專門在此討論。
(1)匯編代碼編寫
使用匯編優(yōu)化有兩個(gè)方法:對(duì)于LEAF函數(shù)(函數(shù)體中不再調(diào)用其余函數(shù)),采用整個(gè)函數(shù)完全用匯編指令重寫的方式;而對(duì)于NONLEAF函數(shù)則可使用asm關(guān)鍵字,在C代碼中嵌入?yún)R編代碼。在匯編代碼的編寫過(guò)程中一些情況會(huì)造成流水線stall,在編寫匯編代碼時(shí)要特別注意避免這些情況。IDE集成了PIPLELINE VIEWER工具,如圖4所示。在編寫完成匯編代碼后,可使用該工具觀察運(yùn)行時(shí)流水線的情況。如果有stall等出現(xiàn),會(huì)給出原因,優(yōu)化人員根據(jù)工具分析結(jié)果重新更改代碼,提高執(zhí)行效率。
ADI公司提供的IDE具有非常靈活的設(shè)置,能根據(jù)用戶的需要生成針對(duì)不同限制的代碼。如內(nèi)存有限,用戶可以設(shè)置生成文件更小的代碼;如果用戶更注重運(yùn)行速度,則設(shè)置編譯器生成運(yùn)行速度更快的代碼,或是在其間取一個(gè)折中。
ADSP-BF561有專門用于處理視頻相關(guān)的一些專用DSP指令(video pixel operations、vector operations等),這些專用指令通過(guò)SIMD技術(shù)或者操作專門硬件支持某些特殊運(yùn)算(累加、多參數(shù)取均值,同時(shí)完成加減法等),以提高運(yùn)行速度。如前文求SAD情況,匯編指令中有指令專門計(jì)算連續(xù)4個(gè)像素與另外連續(xù)4個(gè)像素之差的絕對(duì)值之和,結(jié)果與累加器的值相加。如果要隔點(diǎn)算(即取一半的點(diǎn)計(jì)算),反而需要增加指令后對(duì)數(shù)據(jù)進(jìn)行下采樣,既耗時(shí)而且不準(zhǔn)確。所以采用計(jì)算一半像素點(diǎn)的策略并不適用于ADSP-BF561。編譯器自動(dòng)生成的代碼中不會(huì)使用到這些專用指令。所以只能根據(jù)對(duì)算法的理解和對(duì)平臺(tái)的熟悉程度來(lái)對(duì)算法進(jìn)行匯編優(yōu)化。
在編寫匯編代碼時(shí)還需注意部分寄存器的使用,如I0、I1,其值不僅用做地址索引,還會(huì)影響許多指令的計(jì)算結(jié)果。在使用這些寄存器時(shí),一定要注意將其壓?;蛑脼檫m當(dāng)?shù)闹怠4送?,關(guān)于數(shù)據(jù)的載入,一般應(yīng)遵循對(duì)齊原則,但在做運(yùn)動(dòng)估計(jì)計(jì)算匹配準(zhǔn)則函數(shù)時(shí),這樣的要求往往達(dá)不到。故如能將兩者分開來(lái)計(jì)算,將更能提高效率。
此外,應(yīng)盡量合理地使用寄存器,多使用并行指令也能提高代碼的執(zhí)行效率。
(2)分級(jí)存儲(chǔ)器結(jié)構(gòu)
ADSP-BF561處理器采用改進(jìn)的哈佛結(jié)構(gòu)和分級(jí)的存儲(chǔ)器結(jié)構(gòu)。Level 1(L1)存儲(chǔ)器以全速運(yùn)行,只有很少的延遲。在L1級(jí),指令存儲(chǔ)器存放指令。兩個(gè)數(shù)據(jù)存儲(chǔ)器存放數(shù)據(jù),一個(gè)專用的臨時(shí)數(shù)據(jù)存儲(chǔ)器存放堆棧和局部變量信息。由多個(gè)L1 存儲(chǔ)器組成的模塊,可進(jìn)行SRAM和CACHE 的混合配置。存儲(chǔ)器管理單元(MMU)提供存儲(chǔ)器保護(hù)功能,對(duì)運(yùn)行于內(nèi)核上的獨(dú)立任務(wù),可保護(hù)系統(tǒng)寄存器免于意外的存取。L1 存儲(chǔ)器是ADSP-BF561處理器內(nèi)核中性能最高、最重要的存儲(chǔ)器。通過(guò)外部總線接口單元(EBIU),片外存儲(chǔ)器可以由SDRAM、FLASH 和SRAM 進(jìn)行擴(kuò)展,可以訪問多達(dá)132 MB的物理存儲(chǔ)器。根據(jù)這樣的特點(diǎn),將執(zhí)行率更高的代碼放入L1指令緩存中,能使代碼更快地運(yùn)行。IDE提供了Profile工具,能在運(yùn)行時(shí)統(tǒng)計(jì)各個(gè)函數(shù)所占的CYCLE數(shù)和占總CYCLE數(shù)的百分比。通過(guò)將X264中比較耗時(shí)的部分算法代碼,如模式選擇部分代碼放入L1指令空間,能進(jìn)一步提升運(yùn)行效率。Profile工具統(tǒng)計(jì)結(jié)果同樣也是選擇需要使用匯編優(yōu)化函數(shù)的依據(jù),IDE可根據(jù)Profile結(jié)果對(duì)代碼進(jìn)行優(yōu)化。X264代碼Profile統(tǒng)計(jì)結(jié)果與測(cè)試數(shù)據(jù)有很大關(guān)系,選用更類似以后應(yīng)用場(chǎng)所的數(shù)據(jù)作為測(cè)試數(shù)據(jù),能使統(tǒng)計(jì)結(jié)果更接近以后的應(yīng)用環(huán)境。為達(dá)到比較準(zhǔn)確的統(tǒng)計(jì)結(jié)果,最好在Simulation階段進(jìn)行統(tǒng)計(jì)。雖然這樣非常耗時(shí),但為得到一個(gè)準(zhǔn)確的統(tǒng)計(jì)作為參考依據(jù)是值得的。此外CACHE VIEWER工具能提供運(yùn)行時(shí)CACHE的使用情況,使用它來(lái)分析CACHE的使用,對(duì)于提高代碼運(yùn)行效率很有用處。
評(píng)論