NEON簡單總結

2021-09-25 03:44:50 字數 3361 閱讀 5084

對neon加速做乙個簡單的總結,遇到其他問題再記錄整理,這裡感謝幾位博主的奉獻。

先貼乙個簡單的例子,例子參考

#include#include#include using namespace std;

float sum_array(float* arr,int len);

float sum_array_neon(float* arr,int len);

double time_calc(struct timespec &tp_start, struct timespec &tp_end)

int main()

float sum = vgetq_lane_f32(sum_vec,0)+vgetq_lane_f32(sum_vec,1)+vgetq_lane_f32(sum_vec,2)+vgetq_lane_f32(sum_vec,3);

for(;left4>0;left4--,arr++)

return sum;

}

使用neon首先引入標頭檔案,其次就可以根據neon的程式設計指令進行程式的加速和優化,下面將上面用到的函式介紹如下,此處借用無眠梔的介紹:

上面用到的函式有:

float32x4_t vdupq_n_f32 (float32_t value)

將value複製4分存到返回的暫存器中

float32x4_t vld1q_f32 (float32_t const * ptr)

從陣列中依次load4個元素存到暫存器中

相應的 有void vst1q_f32 (float32_t * ptr, float32x4_t val)

將暫存器中的值寫入陣列中

float32x4_t vaddq_f32 (float32x4_t a, float32x4_t b)

返回兩個暫存器對應元素之和 r = a+b

相應的 有float32x4_t vsubq_f32 (float32x4_t a, float32x4_t b)

返回兩個暫存器對應元素之差 r = a-b

float32_t vgetq_lane_f32 (float32x4_t v, const int lane)

返回暫存器某一lane的值

其他常用的函式還有:

float32x4_t vmulq_f32 (float32x4_t a, float32x4_t b)

返回兩個暫存器對應元素之積 r = a*b

float32x4_t vmlaq_f32 (float32x4_t a, float32x4_t b, float32x4_t c)

r = a +b*c

float32x4_t vextq_f32 (float32x4_t a, float32x4_t b, const int n)

拼接兩個暫存器並返回從第n位開始的大小為4的暫存器 0<=n<=3

例如a: 1 2 3 4

b: 5 6 7 8

vextq_f32(a,b,1) -> r: 2 3 4 5

vextq_f32(a,b,2) -> r: 3 4 5 6

vextq_f32(a,b,3) -> r: 4 5 6 7

關於neon函式的命名規則介紹如下,參考stn_lcd:

資料型別  

neon intrinsics內建的整數資料型別主要包括以下幾種:

(u)int8x8_t;

(u)int8x16_t;

(u)int16x4_t;

(u)int16x8_t;

(u)int32x2_t;

(u)int32x4_t;

(u)int64x1_t;

其中,第乙個數字代表的是資料型別寬度為8/16/32/64位,第二個數字代表的是乙個暫存器中該型別資料的數量。如int16x8_t代表16位有符號數,暫存器中共有8個資料。

常用指令

neon intrinsics支援的所有指令可參看arm neon intrinsics,其包含了常用的arm彙編指令型別,如數**算,邏輯運算等。另外,其引入了有針對性的載入/儲存/轉置/交叉訪問等指令。部分常見的指令在會下面的示例環節中予以說明。需要注意的是,指令中的助記符與arm彙編是相同的。

示例1:

int16x8_t vqaddq_s16 (int16x8_t, int16x8_t)

int16x4_t vqadd_s16 (int16x4_t, int16x4_t)

第乙個字母'v'指明是vector向量指令,也就是neon指令;

第二個字母'q'指明是飽和指令,即後續的加法結果會自動飽和;

第三個字段'add'指明是加法指令;

第四個字段'q'指明操作暫存器寬度,為'q'時操作qword, 為128位;未指明時操作暫存器為dword,為64位;

第五個字段's16'指明操作的基本單元為有符號16位整數,其最大表示範圍為-32768 ~ 32767;

形參和返回值型別約定與c語言一致。

其它可能用到的助記符包括:

l 長指令,資料擴充套件

w 寬指令,資料對齊

n 窄指令, 資料壓縮

示例2 uint8x8_t vld1_u8 (const uint8_t *)

第二個字段'ld'表示載入指令

第三個字段'1'(注意是1,不是l)表示順次載入。如果需要處理影象的rgb分量,可能會用到vld3。關於vld/vst指令更詳細的說明,請自己參閱arm官方文件。

編譯指令介紹如下,此處引用賀二公子的總結:

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 和 VFP 程式設計 NEON通用算術指令

本節包括以下小節 vaba 和 vabd 向量差值絕對值累加和差值絕對值。vabs 和 vneg 向量絕對值和求反。vadd vaddl vaddw vsub vsubl 和 vsubw 向量加法和減法。vaddhn 和 vsubhn 選擇高半部分的向量加法和選擇高半部分的向量減法。vhadd 和 ...

NEON指令化並行技術簡介和簡單使用

向量化simd是一種單指令多資料的並行執行方式。具體而言,向量化是指相同指令在硬體向量處理單元上對多個資料流進行操作。這些硬體向量處理單元也被稱為simd單元。補充 cpu在單位時間內 同一時間 能一次處理的二進位制數的位數稱為字長。1位元組是8位字長。如果每個執行緒能夠充分利用每個處理器核心的si...

neon指令資料解析

參考 向量資料型別 定義了以下型別來表示向量。根據以下模式命名了 neon 向量資料型別 型別 大小 x 向量線條數 t 例如,int16x4 t 是乙個包含四條向量線的向量,每條向量線包含乙個有符號 16 位整數。某些內在函式使用以下格式的向量型別陣列 型別 大小 x 向量線條數 x 陣列長度 t...