對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...