NEON技术粗浅认识
1、簡介
???????? 微處理器處理數(shù)據(jù)主要分為以下幾種:
Single instruction single data—SISD
Single instruction multiple data(vectormode)—SIMD
Single instruction multiple data(packeddata mode)—SIMD
(1)SISD
???????? 一次指令操作一個數(shù)據(jù)。如下例子4次指令操作才完成8個寄存器相加:
addro, r5
add r1,r6
addr2, r7
addr3, r8
?
(2)SIMD(vector mode)
???????? 一次指令可以處理多個數(shù)據(jù),但是每個數(shù)據(jù)處理是順序執(zhí)行,如下:
VADD.F32S24, S8, S16
//S24=S8+S16
//S25=S9+S17
//S26=S10+S18
//S27=S11+S19
一個指令,但是數(shù)據(jù)相加是順序執(zhí)行。在ARM上這個也叫Vector Floating Point(VFP)。
(3)SIMD(packed data mode)
???????? 一次指令可以處理多個數(shù)據(jù),由于使用大寄存器方式可以同時進(jìn)行,如下:
VADD.I16Q10, Q8, Q9
一個指令將兩個64-bit寄存相加,I16表示數(shù)據(jù)類型int16,64-bit= 4 * 16,每個寄存器里4個16-bit lanes獨(dú)立相加,但是同時完成,如圖:
在ARM上這個叫做增強(qiáng)型SIMD技術(shù)或NEON技術(shù)。
2、寄存器信息
???????? 在armv7-A和armv7-R的體系架構(gòu)上基本采用了neon技術(shù),armv8也支持并與armv7兼容。VFP和NEON共用協(xié)處理器CP10和CP11的指令空間和寄存器,并成為ARM/Thumb指令集的一部分。
???????? NEON寄存器就會是由相同數(shù)據(jù)類型組成的元素向量,一個寄存器(即一個向量)劃分為多個管道,每個管道包含一個數(shù)據(jù)元素。每個neon指令就是這些管道元素并行操作,且互相不影響。Neon劃分為兩種向量:64-bit NEON vectors(doubleword簡稱D寄存器)和128-bit NEON vectors(quadword簡稱Q寄存器)。
64-bit NEON vectors包含:
8個8-bit elements(即8個管道,每個管道可以包含8bit的數(shù)據(jù)元素)
4個16-bit elements
2個32-bit elements
1個64-bit elements
128-bit NEONvectors包含:
16個8-bit elements
8個16-bit elments
4個32-bit elements
2個64-bit elements
???????? 這樣劃分就可以neon用在不同場景:像素處理8-bit,顏色處理16-bit等。
管道lane和元素element關(guān)系
執(zhí)行neon指令:VADD.I16 Q0, Q1, Q2,Q代表128-bit寄存器,I16代表16-bit,這句話就是8個16-bit lanes的128-bit向量寄存器相加,如圖所示:
???????? VFP和NEON是共享寄存器空間,因此寄存器存是重疊的,如圖所示:
Neon 寄存器單元:
16個128-bit Q 寄存器,Q0~Q15
32個64-bit D寄存器,D0~D31
VFPv3-D32:
32個64-bit D寄存器,D0~D31
VFPv2或VFPv3-16:
16個64-bit D寄存器,D0~D15
VFP:
16個32-bit S寄存器
neon單元可以訪問Q0寄存器作為一個128-bit寄存器
neon單元可以訪問Q0寄存器作為兩個64-bit寄存器D0和D1
neon不能范圍32-bit的S寄存器,但VFP可以訪問32-bit
???????? 下表是neon支持的數(shù)據(jù)類型:
?
3、neon使用方法
(1)匯編
???????? 通過匯編直接時鐘neon指令:
.text
.arm
.global double_elements
double_elements:
vadd.i32 q0,q0,q0
bx? lr
.end
arm-hisiv300-linux-as -mfloat-abi=softfp-mfpu=neon-vfpv4 neon_as.S
m-hisiv300-linux-as -mfloat-abi=softfp-mfpu=neon-vfpv4 neon_as.S
該種方式效率最高,但是難度大,移植性差
?
(2)使用arm提供的Intrinsics函數(shù)
???????? 可以認(rèn)為是內(nèi)聯(lián)函數(shù),但是在編譯時編譯器會將函數(shù)轉(zhuǎn)化為neon指令。調(diào)用該函數(shù)需要包含頭文件arm_neon.h,該頭文件包含了neon各種操作函數(shù),具體可以該頭文件arm-hisiv300-linux/lib/gcc/arm-hisiv300-linux-uclibcgnueabi/4.8.3/include/arm_neon.h或參考文檔《neon_programmers_guide.pdf》附錄D。
簡單例子:
#include <arm_neon.h>
uint32x4_t double_elements(uint32x4_tinput)
{
???????? return(vaddq_u32(input,input));
}
arm-hisiv300-linux-gcc -mfloat-abi=softfp-mfpu=neon-vfpv4 -c neon_in.c
匯編結(jié)果如下:
?
(3)自動化向量(實(shí)際驗(yàn)證未通過)
???????? 該方式需要對指針參數(shù)添加__restrict(用于限定和約束指針,表明指針是訪問一個數(shù)據(jù)對象的唯一且初始的方式)。簡單例子:
void add_ints(int * __restrictpa, int * __restrict pb, unsigned int n, int x)
{
???????? unsigned int i;
???????? for(i = 0; i < (n & ~3); i++)
?????????????????? pa[i] = pb[i] + x;
}
void add_floats(float *__restrict pa, float * __restrict pb, unsigned int n, float x)
{
??? unsigned int i;
??? for(i = 0; i < (n & ~3); i++)
??????? pa[i] = pb[i] + x;
}
arm-hisiv300-linux-gcc -mfloat-abi=softfp -mfpu=neon-vfpv4-ftree-vectorize?-ftree-vectorizer-verbose=1 -c neon_av.c
匯編如下:
???????? 該方法浮點(diǎn)運(yùn)算會自動轉(zhuǎn)化為neon指令,而整型則不會。從第二小節(jié)可以知道neon支持整型操作,而實(shí)際圖像,顏色等都是整形數(shù)的,該方法對于這些操作就無法發(fā)揮neon指令優(yōu)勢。
?
(4)使用第三方優(yōu)化庫
???????? 以下列舉了已經(jīng)用neon優(yōu)化過的庫,編譯時加入neon參數(shù),然后調(diào)用相應(yīng)接口進(jìn)行操作。
A.Ne10
官網(wǎng):http://projectne10.github.com/Ne10/
git地址:https://github.com/projectNe10/Ne10
C接口函數(shù)提供了匯編和常用處理方法
?
B.OpenMAX DL
???????? 地址:http://www.khronos.org/openmax/ 網(wǎng)站無法打開
OpenMAX由Khronosgroup(也是open Gl制定者)制定的開放多媒體加速層,是一個不需要授權(quán)、跨平臺的軟件抽象層,以C語言實(shí)現(xiàn)的軟件接口,提供了一下系列處理音頻、視頻、靜態(tài)圖片的API。
OpenMAX自上而下分為三個層次:OpenMAX AL,OpenMAXIL和OpenMAX DL。
OpenMAX AL:Application Layer,應(yīng)用和多媒體中間層的標(biāo)準(zhǔn)接口,使得應(yīng)用在多媒體接口上具有了可移植性
OpenMAX IL: Integration Layer,作為在嵌入式和移動設(shè)備中使用的audio,video,images codecs的底層接口。使得AP和多媒體框架可以以統(tǒng)一的方式訪問多媒體codec和支持組件。Codec可以是硬件和軟件的任意組合,對用戶透明。
OpenMAX DL: Development Layer,最底層使用neon進(jìn)行了優(yōu)化
?
C.ffmpeg
官網(wǎng):http://ffmpeg.org/
git地址:https://github.com/FFmpeg/FFmpeg
???????? FFmpeg是一套可以用來記錄、轉(zhuǎn)換數(shù)字音頻、視頻,并能將其轉(zhuǎn)化為流的開源計(jì)算機(jī)程序。采用LGPL或GPL許可證。它提供了錄制、轉(zhuǎn)換以及流化音視頻的完整解決方案。它包含了非常先進(jìn)的音頻/視頻編解碼庫libavcodec,為了保證高可移植性和編解碼質(zhì)量,libavcodec里很多code都是從頭開發(fā)的。
?????? 功能包括視頻采集功能、視頻格式轉(zhuǎn)換、視頻抓圖、給視頻加水印等。
?
D.Eigen3
?????? 官網(wǎng):http://eigen.tuxfamily.org/
?????? Github:https://github.com/artsy/eigen
?????? Eigen是一個高層次的C ++庫,有效支持線性代數(shù),矩陣和矢量運(yùn)算,數(shù)值分析及其相關(guān)的算法
?
E.Pixman
?????? 官網(wǎng):http://pixman.org/
?????? 2D圖形庫
?
F.x264
?????? 官網(wǎng):http://www.videolan.org/developers/x264.html
?
G.Math-neon
?????? 官網(wǎng):http://code.google.com/p/math-neon/
??????
?
(5)hi3536 目前使用neon的方法
?????? 目前,我們只是編譯時添加了參數(shù),未做其他處理:
CFLAGS +=-mfloat-abi=softfp -mfpu=neon-vfpv4 -mno-unaligned-access-fno-aggressive-loop-optimizations。簡單例子;
float sum1(floata, float b)
{
?????? return (a+b);
}
int sum2(int a,int b)
{
?????? return (a+b);
}
arm-hisiv300-linux-gcc -mfloat-abi=softfp -mfpu=neon-vfpv4-c neon.c
匯編如下:
也是對浮點(diǎn)進(jìn)行了neon操作,而整型是保持不變的。
?????? 因此使用的是第三種自動化向量的方法。
?
4、neon應(yīng)用例子
?????? 在《neon_programmers_guide.pdf》文檔中舉了好多個neon使用的例子:
A.交換RGB顏色通道
B.處理非對齊數(shù)組
C.矩陣計(jì)算
D.向量積
E.轉(zhuǎn)換色彩深度
F.中值濾波
G.FIR濾波
?
5、官方參考文檔
?????? Neon資料比價少,在arm官網(wǎng)上可以查到如下幾個資料,第一個是詳細(xì)說明。
《neon_programmers_guide.pdf》
《introducing_neon.pdf》
《neon_support_in_compilation_tools.pdf》
總結(jié)
以上是生活随笔為你收集整理的NEON技术粗浅认识的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 流处理器
- 下一篇: WPF DataGridTextColu