陳思潤 顧乃杰* 蘇俊杰 賀愛香
1(中國科學技術(shù)大學計算機科學技術(shù)學院 安徽 合肥 230027)2(中國科學技術(shù)大學安徽省計算與通信軟件重點實驗室 安徽 合肥 230027)3(中國科學技術(shù)大學先進技術(shù)研究院 安徽 合肥 230027)4(安徽新華學院信息工程學院 安徽 合肥 230088)
近年來,移動終端數(shù)量爆炸式增長[1],且隨著人們對移動設(shè)備圖像視覺的追求日益提高,Android設(shè)備的圖像處理速度難以滿足移動客戶端的海量應(yīng)用發(fā)展需求。而OpenCV作為一款從PC端到嵌入式開發(fā)領(lǐng)域的免費的開源跨平臺計算機視覺庫,可提供從影像過濾及轉(zhuǎn)換到特性抽象與機器學習等幾十個不同類別的數(shù)百種算法[2]。它已被成千上萬的開發(fā)人員所使用,而且仍在不斷發(fā)展之中。
傳統(tǒng)的嵌入式平臺依賴于CPU的串行計算方案,難以處理這類大量的計算密集型問題[3]。針對ARM架構(gòu),OpenCV源碼使用了SIMD(Single Instruction Multiple Data)指令[4]做了部分改寫,實驗分析其仍然存在優(yōu)化的空間。NEON技術(shù)通過對數(shù)據(jù)并行處理,能夠很好地處理矩陣運算等存在大量數(shù)據(jù)相關(guān)性低的計算操作,因此適用于視頻轉(zhuǎn)碼、語音處理、圖像處理等場景。例如文獻[3]使用了NEON技術(shù)以及GPGPU對Jpeg靜態(tài)圖像編碼技術(shù)、Mpeg4動態(tài)圖像編碼技術(shù)進行了優(yōu)化,其編解碼性能提升了四倍左右。文獻[5]使用了NEON技術(shù)在ARM Cortex-A系列的架構(gòu)上實現(xiàn)了AVS多媒體視頻文件解碼工具的加速,實驗證明NEON技術(shù)加速效果明顯。文獻[11]同樣在Cortex-A8處理器架構(gòu)上實現(xiàn)VC-1視頻編解碼軟件的SIMD指令優(yōu)化,解碼性能提升30%以上。
考慮到移動終端用戶對圖像視覺質(zhì)量要求日益提高,本文針對Android平臺的ARM架構(gòu),使用NEON技術(shù)對OpenCV庫中的濾波函數(shù)進行了優(yōu)化,濾波效率提升明顯。
ARMv8是ARM公司在2011年發(fā)布的首款支持64位指令集的處理器架構(gòu)。ARMv8保存了ARMv7架構(gòu)的特性,支持Thumb-2、針對浮點FPU的VFP硬件擴展、DSP 擴展、Thumb指令集、主流的嵌入式OS(Linux、Android、Windows Mobile、Windows Phone、Symbian)、以及支持分支預(yù)測等技術(shù)。除此之外ARMv8還進行了一些功能擴展,支持TrustZone、虛擬化技術(shù)以及NEON advanced SIMD技術(shù)。
本文實驗使用的ARM Cortex-A72處理器是基于ARMv8-A 架構(gòu),支持最新的64位指令集AArch64。AArch64相較于AArch32使用了更少的條件指令,刪除了LDM/STM等實現(xiàn)復(fù)雜的指令,且AArch64指令集對32位和64位指令分別解碼,簡化了解碼表,允許更多先進的分支預(yù)測技術(shù)。此外,ARMv8針對AArch64指令集支持的SIMD指令集做了更多的改進,支持雙精度的浮點運算,在支持NEON指令集擴展的同時,其ARM核和NEON核的執(zhí)行流水線分開執(zhí)行,能夠在16FF+的處理器技術(shù)中實現(xiàn)3 GHz以上的頻率。
SIMD(Single Instruction Multiple Data)意思就是指一條指令能夠同時處理多個數(shù)據(jù)的數(shù)據(jù)級并行計算技術(shù),其執(zhí)行機制如圖1所示。
圖1 SIMD指令機制示意圖
NEON是一種基于SIMD思想的數(shù)據(jù)級并行技術(shù),它旨在加速信號處理算法,能夠加速音頻和視頻處理、語音和面部識別、計算機視覺和深度學習等應(yīng)用技術(shù)。NEON技術(shù)從ARMv7版本開始被采用,目前可以在ARM Cortex-A和Cortex-R系列處理器中使用。NEON結(jié)合了64位和128位的SIMD指令集,ARMv8 NEON 指令集架構(gòu)具有16個128位的四字寄存器,命名為 Q0-Q15,這16個寄存器又可以拆分成 32個64 雙字寄存器,命名為 D0-D31。圖2描述了NEON寄存器在多通道內(nèi)同時進行多數(shù)據(jù)并行計算的過程。
圖2 NEON指令并行計算
研究人員使用NEON技術(shù)進行優(yōu)化主要有四種方法,具體包括匯編優(yōu)化、內(nèi)聯(lián)函數(shù)(intrinsic)、自動向量化以及NEON優(yōu)化庫。
使用手寫匯編的形式,理論上可以達到NEON指令最高的優(yōu)化效果,但是由于需要跟底層寄存器流水線打交道,所以在幾種方法中難度最高,優(yōu)化過程更復(fù)雜。手寫匯編對開發(fā)者要求頗高,要想寫出高效的匯編代碼必須要有一定的匯編基礎(chǔ),以及體系結(jié)構(gòu)相關(guān)的知識。使用不當,則會適得其反影響其性能。
ARM為Cortex-A系列處理器生成NEON代碼定義了一組新的數(shù)據(jù)類型以及C語言形式的內(nèi)聯(lián)函數(shù)接口。在開發(fā)人員進行C/C++語言開發(fā)時形同普通的函數(shù)調(diào)用,且ARMv8版本的NEON指令集支持64位的雙精度浮點運算,擁有更多的指令操作。
調(diào)用ARM官方定義的內(nèi)聯(lián)函數(shù)時,程序需要在代碼中包含頭文件“arm_neon.h”,內(nèi)斂函數(shù)具體數(shù)據(jù)格式以及函數(shù)原型使用方法舉例如下:
#include
uint32x4_t example_func(uint32x4_t input)
{
return(vaddq_u32(input, input));
}
其中uint32x4_t數(shù)據(jù)類型表示使用了128位Q寄存器,并且數(shù)據(jù)類型為無符號的32位整型數(shù)。函數(shù)vaddq_u32完成對兩個寄存器中各個32位無符號整型數(shù)據(jù)的加法操作。
使用內(nèi)聯(lián)函數(shù)相比較于手寫匯編的形式要簡單,對開發(fā)人員而言是一種比較友好的開發(fā)方式,并且大多數(shù)時候優(yōu)化效果接近或者達到手工編寫匯編代碼的形式。
自動向量化是由ARM向量化編譯器提供,需要在編譯時加上相關(guān)的命令參數(shù),如:gcc編譯器使用“-ftree-vectorize”、armcc編譯器使用“-vectorize”來開啟自動向量化功能。這種方法的優(yōu)勢是使用簡單,不需要太多額外工作,且跨平臺移植方便,缺點是該種方式優(yōu)化的效果較差。
Ne10[4]是一個單獨的開源庫,可以把它直接嵌入到項目里面去(目前支持平臺有l(wèi)inux,android,ios)。Ne10已實現(xiàn)了部分功能接口,具體有4個模塊:dsp、math、imgproc、physics。目前Ne10提供的API功能有限,數(shù)據(jù)類型相較于ARM官方的定義也有差異,研究人員使用需要改動甚至重新編寫部分功能函數(shù),容易破壞平臺間的可移植性。
對以上介紹的四種方法,權(quán)衡優(yōu)化效果與使用復(fù)雜程度的關(guān)系,本文選擇使用內(nèi)聯(lián)函數(shù)的方式對OpenCV庫中的濾波函數(shù)進行優(yōu)化,部分熱點代碼使用手寫匯編代碼的方式實現(xiàn)進一步的細致優(yōu)化。
本文針對2.4.13版本的開源代碼OpenCV庫,對濾波函數(shù)進行優(yōu)化,具體使用ARM Cortex-A系列處理器支持的NEON技術(shù)對圖像處理模塊的濾波函數(shù)進行了優(yōu)化。OpenCV主要包含imgproc、features2d、highgui、core、calib3d等模塊。由于OpenCV濾波函數(shù)較多,本文僅以中值濾波函數(shù)為例,說明NEON優(yōu)化思路以及具體實現(xiàn)方式。
中值濾波是由Tukey提出的一個非線性濾波器,對于中值的計算傳統(tǒng)方法是使用排序?qū)崿F(xiàn),標準的一維中值濾波器定義如下:
yi=med{xi-r,xi-r+1,…,xi,…,xi+r}
(1)
式中:med表示取中值操作,具體實現(xiàn)如算法1所示。
算法1傳統(tǒng)中值濾波算法
輸入: imageXsize ism×n,kernel radiusr
輸出:medvalueY
(1) for i=r to m-r do
(2) for j=r to n-r do
(3) initialize list A[r2]
(4) for a = i-r to i+r
(5) for b = j-r to j+r
(6) add X(a, b) to A[r2]
(7) end
(8) end
(9) sort A[r2] then Y(i,j) = A[r2/2]
(10) end
(11) end
根據(jù)中值濾波函數(shù)源碼的實現(xiàn)可知,定義兩個向量X、Y,由于X[i]與Y[i]之間的操作結(jié)果并不影響X[i+1]與Y[i+1]之間的操作結(jié)果,數(shù)據(jù)之間沒有關(guān)聯(lián),理論上可以同時進行而不會改變最終結(jié)果。本文通過使用objdump反匯編工具分析OpenCV中值濾波源碼,發(fā)現(xiàn)未優(yōu)化前每次執(zhí)行完一次加法指令需要額外增加一條cmp和jmp指令,不僅增加了額外的指令開銷也不利于指令流水。而NEON技術(shù)一條指令最大支持8次操作同時并行執(zhí)行,不僅大大減少了條件判斷指令開銷,而且充分利用了ARM處理的多級流水線功能。Cortex-A系列處理器擁有兩級 Cache,且L2級Cache跟NEON有直接相連的接口,方便數(shù)據(jù)交互,這種特性使得數(shù)據(jù)并行能夠順利進行大大減少因cache失效而產(chǎn)生的額外訪存開銷。
根據(jù)分析,中值濾波函數(shù)核心代碼不存在復(fù)雜的邏輯控制語句,且代碼所用的數(shù)據(jù)結(jié)構(gòu)ushort,為16位無符號整數(shù)類型,而NEON的Q寄存器結(jié)構(gòu)支持16x8 bit的數(shù)據(jù)格式,滿足NEON指令集的數(shù)據(jù)對齊的要求。輸入數(shù)據(jù)類型為ushort,剛好可以通過對齊轉(zhuǎn)化到uint16x8_t從而方便NEON處理器的使用。具體轉(zhuǎn)換以定義一個ushort向量HT[16][8]為例,HT[0][0]~HT[15][7]存儲地址連續(xù),根據(jù)C++數(shù)組內(nèi)存為行優(yōu)先的存放規(guī)則可知該二維數(shù)組在內(nèi)存中的存放順序為:HT[0][0],HT[0][1],…,HT[15][7]。通過數(shù)據(jù)類型轉(zhuǎn)換為uint16x8_t類型的RT[16],具體對應(yīng)關(guān)系如圖3所示。
圖3 數(shù)據(jù)類型映射關(guān)系
NEON指令VADD.I16 Q0、Q1、Q2使用Q寄存器實現(xiàn)8路16位無符號整數(shù)的并行加法操作,對比原來的16位無符號整數(shù)的循環(huán)疊加操作,減少了大量時間開銷,8路并行加法具體操作過程如圖4所示。
圖4 8路16位整數(shù)并行加法
vld1.16 {d18-d19}, [r3]
add r3, sp, #36
vld1.16 {d22-d23}, [r3]
add r3, sp, #20
vld1.16 {d16-d17}, [r3]
add r3, sp, #52
vld1.16 {d20-d21}, [r3
四是創(chuàng)新人才匱乏,人才結(jié)構(gòu)性矛盾突出。目前,東營市擁有各類科技人員18.6萬人,但大多數(shù)分布在油田、石油大學以及教育、衛(wèi)生系統(tǒng),而企業(yè)自有一線研發(fā)人員不能充分滿足技術(shù)創(chuàng)新需要,具有特殊專業(yè)技能的高層次人才匱乏,科技創(chuàng)新后勁需進一步加強。
vadd.i16 q9, q9, q11
vadd.i16 q8, q8, q10
ldr r2, [sp, #68
ldr r3, [r4]
add r1, sp, #36
cmp r2, r3
add r3, sp, #52
vst1.16 {d18-d19}, [r1]
vst1.16 {d16-d17}, [r3]
算法2對輸入圖像像素每一列維護一個大小固定的一維列數(shù)組Hist,使用一維列數(shù)組對濾波窗口像素值進行更新,極大地減少了比較操作,快速高效地得到中值。將數(shù)組更新的實現(xiàn)方式移植到ARM平臺,且利用ARM Cortex-A系列支持的NEON技術(shù),使用SIMD單指令多數(shù)據(jù)流的并行計算方法,改進中值濾波算法,具體實現(xiàn)如算法2所示。
算法2優(yōu)化中值濾波算法
輸入: imageXsize ism×n,kernel radiusr
輸出:medvalueY
(1) 初始化列數(shù)組Hist1…n,kernelH,左右圖片邊界添加m/2個像素點,上下邊界添加n/2個像素點;
(2) for i=1 to m do
(3) for j=1 to n step 8 do
(4) Remove Xi-r-1,j+r from Histj+r
(5) //NEON 并行計算
(6) SIMD_add Xi+r,j+r<- Histj+r
(7) SIMD_sub Histj+r<- Histj-r-1
(8) SIMD_add H <- Histj+r
(9) //更新濾波中值結(jié)果
(10) Y(i,j) <- median(H)
(11) end
(12) end
算法2的核心思想是對輸入圖像的每一列維護一個一維列數(shù)組Hist,逐行遍歷圖像像素點,以每次遍歷的當前像素為窗口中心像素,建立濾波窗口,提取窗口內(nèi)所有像素值(N=m×n),獲取擁有N個像素點的一維數(shù)組Hist。累加數(shù)組Hist中的每個像素點數(shù)。將步驟(8)更新后的數(shù)組H的中值賦值給窗口中心元素,完成中值濾波操作。分析可知,每次操作的空間只是對一維數(shù)組Hist進行更新,且算法2中第(6)、(7)、(8)步定義的SIMD_add以及SIMD_sub操作均是使用NEON數(shù)據(jù)并行技術(shù)實現(xiàn),具體實現(xiàn)方式為3.4節(jié)介紹的匯編形式,且在3.4節(jié)給出了SIMD_add的詳細匯編指令序列。
對算法2時間復(fù)雜度進行分析,Hist的更新操作可在常數(shù)時間完成,每次求中值操作,只是對大小固定的數(shù)組Hist進行操作,其復(fù)雜度為O(1)時間,對于m×n的圖片,時間復(fù)雜度約為O(mn),相較于傳統(tǒng)方法復(fù)雜度大大降低。
本文實驗所用平臺為ARM,系統(tǒng)使用linux kernel 3.4.35版本,具體CPU型號為Cortex-A72,GPU為maliT880。
實驗使用arm-linux-gcc交叉編譯器,首先通過修改OpenCV目錄的cmake文件設(shè)置好編譯環(huán)境,然后在linux平臺交叉編譯OpenCV源碼,最后通過adb shell工具連接ARM開發(fā)板將生成的可執(zhí)行文件發(fā)送到開發(fā)板進行相關(guān)性能測試。
針對中值濾波函數(shù),分別使用3×3、5×5的采集窗口對所選測試用例進行算法正確性測試。給出256×256像素的帶椒鹽噪聲的圖片用例,觀察濾波函數(shù)優(yōu)化后的濾波效果。
圖5為不同窗口的中值濾波效果圖,其中(a)為帶椒鹽噪聲的測試用例圖片,(b)、(c)分別為3×3、5×5的中值濾波后的圖片,可以看出優(yōu)化后濾波效果明顯,說明優(yōu)化后去噪性能并沒有降低。
圖5 中值濾波效果圖
使用OpenCV自帶python腳本對中值濾波優(yōu)化前后性能進行對比測試,表1給出了中值濾波函數(shù)分別使用3×3、5×5兩種采集窗口在127×61、320×240、640×480、1 280×720這四種不同尺寸的圖片上的對比優(yōu)化效果。分析表中數(shù)據(jù)可以得知,采用NEON技術(shù)優(yōu)化后的中值濾波函數(shù),在不同尺寸圖像以及不同的采集窗口均有很好的優(yōu)化效果,平均加速比均超過了18倍,最高加速比達35倍多,優(yōu)化效果顯著。
表1 中值濾波測試結(jié)果 ms
同時本文對OpenCV庫的其他濾波函數(shù)進行了同樣的加速比測試。由于各類濾波函數(shù)均存在大量矩陣運算操作,數(shù)據(jù)相關(guān)性低,且存在大量重復(fù)計算操作,采用NEON SIMD數(shù)據(jù)級并行技術(shù)對各濾波函數(shù)進行優(yōu)化,效果均表現(xiàn)良好。
測試用例統(tǒng)一使用256×256尺寸的圖片。通過python腳本測試各濾波函數(shù),多次測試分別得出的各濾波函數(shù)濾波時間,經(jīng)過計算得出各函數(shù)對應(yīng)的加速比的平均值。
圖6給出了優(yōu)化后的各濾波函數(shù)分別在3×3以及5×5兩種窗口下的加速比數(shù)據(jù)。從圖中可以看出NEON優(yōu)化加速效果明顯,各函數(shù)加速比均超過兩倍,其中中值濾波函數(shù)優(yōu)化加速比達17倍之多,且隨著濾波窗口的增大,加速比也隨之增大,對應(yīng)其優(yōu)化效果越好。
圖6 濾波函數(shù)加速比
本文針對ARM架構(gòu),根據(jù)OpenCV函數(shù)庫的性能提升需求,使用了NEON數(shù)據(jù)并行技術(shù)對濾波函數(shù)進行了優(yōu)化。實驗證明NEON技術(shù)在OpenCV源碼中優(yōu)化效果顯著,SIMD數(shù)據(jù)級并行優(yōu)化方法能較好地提高濾波函數(shù)的時間性能。
針對ARM架構(gòu),除了NEON技術(shù)可用于優(yōu)化,還可以考慮利用GPU優(yōu)化,以及利用ARM多線程進行相關(guān)優(yōu)化。下一步將著重從GPU、多線程技術(shù)展開進一步的優(yōu)化工作。