日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ARM NEON寄存器

發布時間:2023/12/8 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ARM NEON寄存器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

/*
?* 2020/4/2?? ?10:51?? ?yin
?*
?* 如何才能快速到寫出高效的指令代碼? 這就需要對各個指令比較熟悉,知道各個指令的使用規范和使用場合。
?*/

?? ?32bit NEON寄存器是Q0~Q15共計16個

?? ?64bit NEON寄存器是V0~V31共計32個。

?? ?AArch32狀態下的NEON寄存器組,Q0~Q15,同時對應D0~D32,一個Q分為兩個D,這兩個D是可以單獨操作的;

?? ?其次就是一個D分解為2個S,注意哦只有D0~D15才可分解,共計32個S寄存器;如果要計算浮點值的話你得先把數據搬運到
?? ?這個寄存器(而不是R0~R15中)才能進行浮點運算。

?? ?可以看到特點是寄存器是連續的,Q0等價于D0+D1等價于S0+S1+S2+S3,這在我們做矢量運算的時候是很方便的(實例中可以見到),
?? ?但是在AArch64狀態下的NEON寄存器組可就不一樣。

?? ?V0對應AArch32狀態下Q0,這里只對應D0,跟AArch32不同的是D1分配到V1中去了,也就是說寄存器不連續了,這里可能有人有疑問,
?? ?假如我要把數據放到V0的上班部分怎么辦呢?這個當然考慮到了比如smlal2指令就是專門處理這類問題的

/*
?* SIMD
?*/

?? ?Single Instruction Multiple Data,單指令多數據流。反之SISD是單指令單數據。

?? ?以加法指令為例,單指令單數據(SISD)的CPU對加法指令譯碼后,執行部件先訪問內存,取得第一個操作數;之后再一次訪問內存,
?? ?取得第二個操作數;隨后才能進行求和運算。
?? ?
?? ?而在SIMD型的CPU中,指令譯碼后幾個執行部件同時訪問內存,一次性獲得所有操作數進行運算。這個特點使SIMD特別適合于多媒體應用等數據密集型運算。

?? ?(1)SISD

???????? 一次指令操作一個數據。如下例子4次指令操作才完成8個寄存器相加:

?? ??? ?addro, r5
?? ??? ?add r1,r6
?? ??? ?addr2, r7
?? ??? ?addr3, r8?? ??? ?

?? ?(2)SIMD(vector mode)

?? ??? ?一次指令可以處理多個數據,但是每個數據處理是順序執行,如下:

?? ??? ?VADD.F32S24, S8, S16

?? ??? ?//S24=S8+S16
?? ??? ?//S25=S9+S17
?? ??? ?//S26=S10+S18
?? ??? ?//S27=S11+S19

?? ??? ?一個指令,但是數據相加是順序執行。在ARM上這個也叫"Vector Floating Point(VFP)。"

?? ?(3)SIMD(packed data mode)

?? ??? ?一次指令可以處理多個數據,由于使用大寄存器方式可以同時進行,如下:

?? ??? ?VADD.I16Q10, Q8, Q9

?? ??? ?一個指令將兩個64-bit寄存相加,I16表示數據類型int16,64-bit= 4 * 16,每個寄存器里4個16-bit lanes獨立相加,但是同時完成

?? ?"在ARM上這個叫做增強型SIMD技術或NEON技術。"

/*
?* NEON
?*/

?? ?NEON指令是專門針對大規模到并行運算而設計的。
?? ?
?? ?NEON 技術可加速多媒體和信號處理算法(如視頻編碼/解碼、2D/3D 圖形、游戲、音頻和語音處理、圖像處理技術、電話和聲音合成),
?? ?其性能至少為ARMv5 性能的3倍,為 ARMv6 SIMD性能的2倍。

/*
?* NEON 寄存器
?*/
?? ?有16個128位四字到寄存器Q0-Q15,32個64位雙子寄存器D0-D31,兩個寄存器是重疊的,在使用到時候需要特別注意,不小心就會覆蓋掉。

?? ?兩個寄存器的關系:Qn =D2n和D2n+1,如Q8是d16和d17的組合

/*
?* NEON 數據類型SSSSSS
?*/
?? ?注意數據類型針對到時操作數,而不是目標數,這點在寫的時候要特別注意,很容易搞錯,尤其是對那些長指令寬指令的時候,因為經常Q和D一起操作。

?? ??? ??? ??? ??? ??? ?8 bit?? ?16 bit?? ??? ?32 bit?? ??? ?64 bit
?? ?無符號整數?? ??? ??? ?U8?? ??? ?U16?? ??? ??? ?U32?? ??? ??? ?U64
?? ?有符號整數?? ??? ??? ?S8?? ??? ?S16?? ??? ??? ?S32?? ??? ??? ?S64
?? ?未指定類型的整數?? ?I8?? ??? ?I16?? ??? ??? ?I32?? ??? ??? ?I64
?? ?浮點數?? ??? ??? ??? ?不可用?? ?不可用?? ??? ?F(或F32)?? ?不可用
?? ?{0,1}上的多項式?? ??? ?P8?? ??? ?P16?? ??? ??? ?不可用?? ??? ?不可用


/*
?* NEON中的正常指令、寬指令、窄指令、飽和指令、長指令
?*/
?? ?正常指令(q):生成大小相同且類型通常與操作數向量相同到結果向量

?? ?長指令(l):對雙字向量操作數執行運算,生產四字向量到結果。所生成的元素一般是操作數元素寬度到兩倍,并屬于同一類型。L標記,如VMOVL。

?? ?寬指令(w):一個雙字向量操作數和一個四字向量操作數執行運算,生成四字向量結果。W標記,如VADDW。

?? ?窄指令(n):四字向量操作數執行運算,并生成雙字向量結果,所生成的元素一般是操作數元素寬度的一半。N標記,如VMOVN。

?? ?飽和指令(q):當超過數據類型指定到范圍則自動限制在該范圍內。Q標記,如VQSHRUN


/*
?* NEON指令
?*
?*?? ?V開頭的都是A32/T32指令集
?*/
?? ?復制指令:

?? ??? ?VMOV:

?? ??? ??? ?兩個arm寄存器和d之間

?? ??? ??? ??? ?vmov d0, r0, r1:將r1的內容送到d0到低半部分,r0的內容送到d0到高半部分

?? ??? ??? ??? ?vmov r0, r1, d0:將d0的低半部分送到r0,d0的高半部分內容送到r1

?? ??? ??? ??? ?一個arm寄存器和d之間

?? ??? ??? ??? ?vmov.U32 d0[0], r0:將r0的內容送到d0[0]中,d0[0]指d0到低32位

?? ??? ??? ??? ?vmov.U32 r0, d0[0]:將d0[0]的內容送到r0中

?? ??? ??? ?立即數:

?? ??? ??? ??? ?vmov.U16 d0, #1:將立即數1賦值給d0的每個16位

?? ??? ??? ??? ?vmov.U32 q0, #1:將立即數1賦值給q0的每個32位

?? ??? ??? ??? ?長指令:VMOVL:d賦值給q

?? ??? ??? ??? ?vmovl.U16 q0, d0:將d0的每個16位數據賦值到q0的每個32位數據中

?? ??? ??? ??? ?窄指令:VMOVN:q賦值給d

?? ??? ??? ??? ?vmovn.I32 d0, q0:將q0的每32位數據賦值到q0的每16位數據中

?? ??? ??? ??? ?飽和指令:VQMOVN等,飽和到指定的數據類型

?? ??? ??? ??? ? vqmovun.S32 d0, q0:將q0到每個32位移動到d0中到每個16位中,范圍是0-65535
?? ??? ??? ?

?? ??? ?VDUP:

?? ??? ??? ?VDUP.8 d0, r0:將r0復制到d0中,8位

?? ??? ??? ?VDUP.16 q0, r0:將r0復制到q0中,16位

?? ??? ??? ?VDUP.32 q0, d2[0]:將d2的一半復制到q0中

?? ??? ??? ?VDUP.32 d0, d2[1]:將d2的一半復制到d0中

?? ??? ??? ?注意是vdup可以將r寄存器中的內容復制到整個neon寄存器中,不能將立即數進行vdup,立即數只能用vmov
?? ?

?? ?邏輯運算:

?? ??? ?VADD:按位與;VBIC:位清除;VEOR:按位異或;VORN:按位或非;VORR:按位或


?? ?移位指令:

?? ??? ?VSHL:左移、VSHLL:左移擴展、VQSHL:左移飽和、VQSHLU:無符號左移飽和擴展

?? ??? ?VSHR:右移、VSHRN:右移窄、VRSHR:右移舍入、VQSHRUN:無符號右移飽和舍入


?? ?通用算術指令:

?? ??? ?VABA:絕對值累加、VABD:絕對值相加、VABS:絕對值、VNEG:求反、VADD、VADDW、VADDL、VSUB、VSUBL、VSUBW:加減

?? ??? ?VPADD:將兩個向量的相鄰元素相加

?? ??? ?如VPADD.I16 {d2}, d0, d1

?? ??? ?VPADDL:VPADDL.S16 d0, d1

?? ??? ?VMAX:最大值,VMIN:最小值

?? ??? ?VMUL、VMULL、VMLA(乘加)、VMLS(乘減)、


?? ?加載存儲指令:

?? ??? ?VLD和VST
?? ??? ?
?? ??? ?VREV反轉元素指令:
?? ??? ?
?? ??? ?VEXT移位指令:
?? ??? ?
?? ??? ?VTRN轉置指令:可以用于矩陣的轉置
?? ??? ?
?? ??? ?VZIP指令:壓縮,類似交叉存取
?? ??? ?
?? ??? ?VUZP指令:解壓操作,類似交叉存取
?? ??? ?
?? ??? ?VTBL查表指令:從d0,d1中查找d3中的索引值,如果找到則取出,沒有找到則為0,存入d2中

/*
?* 需要注意的地方
?*/
?? ?load數據的時候,第一次load會把數據放在cache里面,只要不超過cache的大小,下一次load同樣數據的時候,則會比第一次load要快很多,
?? ?會直接從cache中load數據,這樣在匯編程序設計的時候是非常需要考慮的問題。

?? ?如:求取一個圖像的均值,8*8的窗口,先行求和,然后列求和出來均值,這時候會有兩個函數,數據會加載兩遍,如果按照這樣去優化的話則優化不了多少。
?? ?如果換成上面這種思路,先做行16行,然后再做列,這樣數據都在cache里面,做列的時候load數據會很快。

?? ?在做neon乘法指令的時候會有大約2個clock的阻塞時間,如果你要立即使用乘法的結果,則就會阻塞在這里,在寫neon指令的時候需要特別注意。
?? ?乘法的結果不能立即使用,可以將一些其他的操作插入到乘法后面而不會有時間的消耗。

?? ?如:vmul.u16 q1, d3, d4

?? ??? ?vadd.u32 q1, q2, q3

?? ?此時直接使用乘法的結果q1則會阻塞,執行vadd需要再等待2個clock的時間

?? ?使用飽和指令的時候,如乘法飽和的時候,在做乘法后會再去做一次飽和,所以時間要比直接做乘法要慢。

?? ??? ?如:vmul.u16 q1, d3, d4

?? ??? ??? ?vqmul.u32 q1, q2, q3

?? ?后一個的時間要比第一個的時間要久。

?? ?在對16位數據進行load或者store操作的時候,需要注意的是字節移位。比如是16位數據,則load 8個16位數據,如果指定寄存器進行偏移,此時需要特別注意。

?? ??? ?例如:vld1.64 {d0}, [r0], r1


/*
?* 常用的編譯器選項配置
?*/

?? ?自動向量化選項

?? ? armcc編譯器使用–vectorize選項來使能向量化編譯,一般選擇更高的優化等級如-O2或者-O3就能使能–vectorize選項。

?? ? gcc編譯器的向量化選項-ftree-vectorize來使能向量化選項,使用-O3會自動使能-ftree-vectorize選項。

?? ?選擇處理器類型

?? ? armcc編譯器使–cpu 7-A或者–cpu Cortex-A8來指定指令集架構和CPU類型。

?? ? gcc編譯器的處理器選項-mfpu=neon和-mcpu來指定cpu類型。如-mcpu=cortex-a5

?? ?選擇NEON和VFP類型

?? ? gcc選擇用-mfpu=vfpv3-fp16來指定為vfp協處理,而-mfpu=neon-vfpv4等就能指定為NEON+VFP結構。

?? ?選擇浮點處理器和ABI接口類型

?? ? -mfloat-abi=soft使用軟件浮點庫,不是用VFP或者NEON指令;-mfloat-abi=softfp使用軟件浮點的調用規則,而可以使用VFP和NEON指令,
?? ??? ??? ??? ??? ??? ?編譯的目標代碼和軟件浮點庫鏈接使用;

?? ? -mfloat-abi=hard使用VFP和NEON指令,并且改變ABI調用規則來產生更有效率的代碼,如用vfp寄存器來進行浮點數據的參數傳遞,
?? ??? ??? ??? ??? ??? ?從而減少NEON寄存器和ARM寄存器的拷貝。

/*
?* 常用的CPU類型編譯器選項
?*/
?? ?CPU類型 ?? ?CPU類型選項 ?? ?FP選項 ?? ?FP + SIMD選項 ?? ?備注
?? ?Cortex-A5 ?? ?-mcpu=cortex-a5 ?? ?-mfpu=vfpv3-fp16
?? ?-mfpu=vfpv3-d16-fp16 ?? ?-mfpu=neon-fp16 ?? ?-d16表明只有前16個浮點寄存器可用
?? ?Cortex-A7 ?? ?-mcpu=cortex-a7 ?? ?-mfpu=vfpv4
?? ?-mfpu=vfpv4-d16 ?? ?-mfpu=neon-vfpv4 ?? ?-fp16表明支持16bit半精度浮點操作
?? ?Cortex-A8 ?? ?-mcpu=cortex-a8 ?? ?-mfpu=vfpv3 ?? ?-mfpu=neon ?? ?
?? ?Cortex-A9 ?? ?-mcpu=cortex-a9 ?? ?-mfpu=vfpv3-fp16
?? ?-mfpu=vfpv3-d16-fp16 ?? ?-mfpu=neon-fp16 ?? ?
?? ?Cortex-A15 ?? ?-mcpu=cortex-a15 ?? ?-mfpu=vfpv4 ?? ?-mfpu=neon-vfpv4 ?? ?

/*
?* NEON匯編和EABI程序調用規范
?*/
GNU assembler (gas) and ARM Compiler toolchain assembler(armasm)都支持NEON指令的匯編。但必須遵循
?? ?ARMEmbedded Application Binary Interface (EABI)EABI的規范,即NEON寄存器的S0-S15 (D0-D7, Q0-Q3)用于傳遞參數和返回值,
?? ?被調用函數內可以直接使用,不用保存;D16-D31 (Q8-Q15)則有調用函數來保存,被調用函數內可以不保存的隨意使用;而S16-S31(D8-D15, Q4-Q7)
?? ?則必須由被調用函數內部保存。對于調用傳參規范則有,對于軟件浮點,參數有R0~R3和堆棧stack傳遞,而硬件浮點,可以通過NEON寄存器來傳遞參數。


/*
?* 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
?? ?arm-hisiv300-linux-as -mfloat-abi=softfp-mfpu=neon-vfpv4 neon_as.S

?? ?該種方式效率最高,但是難度大,移植性差

(2)使用arm提供的Intrinsics函數

?? ?可以認為是內聯函數,但是在編譯時編譯器會將函數轉化為neon指令。調用該函數需要包含頭文件arm_neon.h,該頭文件包含了neon各種操作函數,
?? ?具體可以該頭文件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

(3)自動化向量(實際驗證未通過)

???????? 該方式需要對指針參數添加__restrict(用于限定和約束指針,表明指針是訪問一個數據對象的唯一且初始的方式)。


/*
?* neon應用例子
?*/
?? ?在《neon_programmers_guide.pdf》文檔中舉了好多個neon使用的例子:

?? ?A.交換RGB顏色通道

?? ?B.處理非對齊數組

?? ?C.矩陣計算

?? ?D.向量積

?? ?E.轉換色彩深度

?? ?F.中值濾波

?? ?G.FIR濾波

/*
?* 官方參考文檔
?*/

?? ?Neon資料比價少,在arm官網上可以查到如下幾個資料,第一個是詳細說明。

?? ?《neon_programmers_guide.pdf》

?? ?《introducing_neon.pdf》

?? ?《neon_support_in_compilation_tools.pdf》

總結

以上是生活随笔為你收集整理的ARM NEON寄存器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。