neon使用和建议
1.neon的使用方法
- NEON優(yōu)化庫(Optimized libraries)
- 向量化編譯器(Vectorizing compilers)
- NEON intrinsics
- NEON assembly
? ? ? ?根據(jù)優(yōu)化程度需求不同,第4種最為底層,若熟練掌握效果最佳,一般也會(huì)配合第3種一起使用。本文將會(huì)重點(diǎn)介紹第3、4種方法。先簡(jiǎn)要介紹前兩種:
(1)Libraries:直接在程序中調(diào)用優(yōu)化
- Ne10:一個(gè)ARM的開源項(xiàng)目,提供數(shù)學(xué)運(yùn)算、圖像處理、FFT函數(shù)等。
- Libyuv :一個(gè)包含YUV數(shù)據(jù)的轉(zhuǎn)換和擴(kuò)展功能的開源庫。
- Skia :一個(gè)開源的2D圖形庫,用作谷歌Chrome和Chrome OS、Android、Mozilla Firefox和Firefox OS以及其他許多產(chǎn)品的圖形引擎。
- OpenMax DL:支持加速視頻編解碼、信號(hào)處理、色彩空間轉(zhuǎn)換等。
(2)Vectorizing compilers:GCC編譯器的向量?jī)?yōu)化選項(xiàng)
- 在GCC選項(xiàng)中加入向量化表示能有助于C代碼生成NEON代碼,如-ftree-vectorize。
2.NEON intrinsics
? ? ? 提供了一個(gè)連接NEON操作的C函數(shù)接口,編譯器會(huì)自動(dòng)生成相關(guān)的NEON指令,支持ARMv7-A或ARMv8-A平臺(tái)。所有的intrinsics函數(shù)都在:GNU官方說明文檔.
一個(gè)簡(jiǎn)單的例子:
//add for int array. assumed that count is multiple of 4#include<arm_neon.h>// C version void add_int_c(int* dst, int* src1, int* src2, int count) {int i;for (i = 0; i < count; i++)dst[i] = src1[i] + src2[i];} }// NEON version void add_float_neon1(int* dst, int* src1, int* src2, int count) {int i;for (i = 0; i < count; i += 4){int32x4_t in1, in2, out;in1 = vld1q_s32(src1);src1 += 4;in2 = vld1q_s32(src2);src2 += 4;out = vaddq_s32(in1, in2);vst1q_s32(dst, out);dst += 4;} }? ? ? ? 代碼中的vld1q_s32會(huì)被編譯器轉(zhuǎn)換成vld1.32 {d0, d1}, [r0]指令,同理vaddq_s32和vst1q_s32被轉(zhuǎn)換成vadd.i32 q0, q0, q0,vst1.32 {d0, d1}, [r0]。若不清楚指令意義,請(qǐng)參見ARM? Compiler armasm User Guide - Chapter 12 NEON and VFP Instructions。?
3.NEON asssembly
NEON可以有兩種寫法:
(1)Assembly文件
- 純匯編文件,后綴為”.S”或”.s”。注意對(duì)寄存器數(shù)據(jù)的保存。具體對(duì)通用寄存器的詳解不是本文的重點(diǎn),有興趣的讀者請(qǐng)自行補(bǔ)充該部分知識(shí)。
(2)inline assembly內(nèi)聯(lián)匯編
- 優(yōu)點(diǎn):在C代碼中嵌入?yún)R編,調(diào)用簡(jiǎn)單,無需手動(dòng)存儲(chǔ)寄存器
- 缺點(diǎn):有較為復(fù)雜的格式需要事先學(xué)習(xí),不好移植到其他語言環(huán)境。
比如上述intrinsics代碼產(chǎn)生的匯編代碼為:
// ARMv7-A/AArch32 void add_float_neon2(int* dst, int* src1, int* src2, int count) {asm volatile ("1: \n""vld1.32 {q0}, [%[src1]]! \n""vld1.32 {q1}, [%[src2]]! \n""vadd.f32 q0, q0, q1 \n""subs %[count], %[count], #4 \n""vst1.32 {q0}, [%[dst]]! \n""bgt 1b \n": [dst] "+r" (dst): [src1] "r" (src1), [src2] "r" (src2), [count] "r" (count): "memory", "q0", "q1"); }4.NEON優(yōu)化心得
建議的NEON調(diào)優(yōu)步驟:
理清所需的寄存器、指令。 建議根據(jù)要實(shí)現(xiàn)的任務(wù),畫出數(shù)據(jù)變換流程,和每步所需的具體指令,盡可能找到最優(yōu)的實(shí)現(xiàn)流程。這一步非常關(guān)鍵,如果思路出錯(cuò)或是不夠優(yōu)化,則會(huì)影響使用NEON的效果,并且對(duì)程序修改帶來麻煩,一定要找到最優(yōu)的實(shí)現(xiàn)算法哦~
先實(shí)現(xiàn)intrinsics(可選)。 初學(xué)者先實(shí)現(xiàn)intrinsics是有好處的,字面理解性更強(qiáng),且有助于理解NEON指令。建議隨時(shí)打印關(guān)鍵步驟的數(shù)據(jù),以檢查程序的正誤。
寫成匯編進(jìn)一步優(yōu)化。 將intrinsics生成的匯編代碼進(jìn)行優(yōu)化調(diào)整。一般來說,有以下幾點(diǎn)值得注意【干貨】:
- 只要intrinsics運(yùn)算指令足夠精簡(jiǎn),運(yùn)算類的匯編指令就不用大修;
- 大部分的問題會(huì)出在存取、移動(dòng)指令的濫用、混亂使用上;
- 優(yōu)化時(shí)要盡量減少指令間的相關(guān)性,包括結(jié)構(gòu)相關(guān)、數(shù)據(jù)相關(guān)控制相關(guān),保證流水線執(zhí)行效率更高;
- 大概估算所有程序指令取指、執(zhí)行、寫回的總理論時(shí)間,以此估算本程序可以優(yōu)化的空間;
- 熟練對(duì)每條指令準(zhǔn)備發(fā)射、寫回時(shí)間有一定的認(rèn)識(shí),有助于對(duì)指令的優(yōu)化排序;
- 一定要多測(cè)試不同指令的處理時(shí)間!!原因是你所想跟實(shí)際有出入,且不同的編譯器優(yōu)化的效果可能也有些不同;
- 一定要有一定的計(jì)算機(jī)體系結(jié)構(gòu)基礎(chǔ),對(duì)存儲(chǔ)結(jié)構(gòu)、流水線有一定的體會(huì)!!
【注意】在此筆者溫馨提示各位看官(⊙o⊙)不僅是NEON,所有的性能優(yōu)化是個(gè)經(jīng)驗(yàn)活兒,需要自己動(dòng)手才能領(lǐng)悟更多的訣竅,總結(jié)一下NEON優(yōu)化就是:
- 第一優(yōu)化算法實(shí)現(xiàn)流程;
- 第二優(yōu)化程序存取;
- 第三優(yōu)化程序執(zhí)行;
- 第四哪兒能優(yōu)化,就優(yōu)化哪兒~~
對(duì)NEON優(yōu)化使用的好壞直接導(dǎo)致優(yōu)化效果,優(yōu)化效果好的會(huì)節(jié)省70%以上的時(shí)間。
5.內(nèi)聯(lián)匯編使用心得
? ? ? ?當(dāng)讀者熟練后就可以直接上手內(nèi)聯(lián)匯編了。時(shí)間有限,本文中不具體介紹inline assembly的使用方法,我后續(xù)可能會(huì)將這部分單獨(dú)寫成一篇博客。感興趣者請(qǐng)參見ARM GCC Inline Assembler Cookbook
一些使用心得:
- inline assembly下面的三個(gè)冒號(hào)一定要注意
- output/input registers的寫法一定要寫對(duì),clobber list也一定要寫完全,否則會(huì)造成令你頭疼的問題 (T-T) …
- 這個(gè)問題在給出的cookbook中也有介紹,但是并不全面,有些問題只有自己碰到了再去解決。 筆者就曾經(jīng)被虐了很久,從生成的匯編發(fā)現(xiàn)編譯器將寄存器亂用,導(dǎo)致指針操作完全混亂,毫無頭緒…
- 一般情況下建議的寫法舉例:
- 傳入內(nèi)聯(lián)匯編程序段的C參數(shù)是有限的
- 筆者親測(cè)對(duì)于Cortex-A7平臺(tái)output/input registers基本在9以內(nèi)才可保證,否則會(huì)報(bào)出can't find a register in class 'GENERAL_REGS' while reloading 'asm'錯(cuò)誤。
?
?
? ?
總結(jié)
- 上一篇: 1BIT,1BYTE,1KB,1MB,1
- 下一篇: 搜索引擎使用技巧汇总,一篇就够了