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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

NEON快速入门

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

NEON

  • 1.簡介
  • 2.簡單實例
  • 3.總結

1.簡介

沒有長篇大論,只用于NEON快速入門!
SIMD:

  • 單指令處理多個數據的并行技術
  • 例如在C語言中對一個int[8]的數組里每一個數都執行加1操作,SIMD技術可以通過一條add指令并行處理;而通常我們自己寫for循環需要執行8次add才能完成,耗時更多

NEON:

  • 一種基于SIMD并適用于ARM的技術,從ARM-V7開始被采用,目前可以在ARM Cortex-A和Cortex-R系列處理器中使用
  • 寄存器,用于存放需要操作的數據;16個128bit的寄存器(128bit代表最大長度,對于int類型數據,能存放4個,對于char類型數據能存放16個,也就是說我能直接把int[4]或者char[16]直接放到128bit的寄存器中)、32個64bit寄存器
  • 支持的數據類型,上官網查詢
  • 常用操作:加減乘除,數據之間的讀寫等

2.簡單實例

實例內容:兩個長度為5000的int型數組相加,把每個結果存入另一個長度為5000的數組當中,對比純C語言實現和NEON實現的性能。
純C實現函數:平平無奇,誰都能寫

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實現函數:
int32x4_t in1, in2, out:用于存放4個int型數據的變量,int32x4_t是一個數據類型聲明(和int效果一致),類似的還有int16x8_t(用于存放8個short類型數據)、int8x16_t(用于存放16個char類型數據),更詳細的去官網查詢
in1 = vld1q_s32(src1):將指針src1的4個數據加載到in1當中,vld1q_s32用于加載int型的數據,并且只會是4個數據,其余類型的加載函數自行查詢,但都是相對應的
src1 += 4:數據加載完成后,指針向后移動4位,用于后續數據加載
out = vaddq_s32(in1, in2):執行in1和in2兩個向量相加操作,并存入out中
vst1q_s32(dst, out):將out里的數據存入dst指針指向的內存中
完畢!

void add_int_neon(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;} }

整體代碼

#include<time.h> #include<stdio.h> #include<stdlib.h> #include<arm_neon.h>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]; }void add_int_neon(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;} }int main() {/* 數據內存分配,初始化 */int size = 5000;int *dst = (int*)malloc(size * sizeof(int));int *src1 = (int*)malloc(size * sizeof(int));int *src2 = (int*)malloc(size * sizeof(int));for(int i = 0; i < size; i++){src1[i] = i;src2[i] = i;}/* 時間初始化 */struct timespec time1_img = {0, 0};struct timespec time2_img = {0, 0};clock_gettime(CLOCK_REALTIME, &time1_img);for(int i = 0; i < size; i++){add_int_c(dst, src1, src2, size);}clock_gettime(CLOCK_REALTIME, &time2_img);printf("C time:%d ms\n", (time2_img.tv_sec - time1_img.tv_sec)*1000 + (time2_img.tv_nsec - time1_img.tv_nsec)/1000000);printf("dst[0]:%d\n", dst[0]);memset(dst, 0, size);clock_gettime(CLOCK_REALTIME, &time1_img);for(int i = 0; i < size; i++){add_int_neon(dst, src1, src2, size);}clock_gettime(CLOCK_REALTIME, &time2_img);printf("Neon time:%d ms\n", (time2_img.tv_sec - time1_img.tv_sec)*1000 + (time2_img.tv_nsec - time1_img.tv_nsec)/1000000);printf("dst[0]:%d\n", dst[0]);free(dst);free(src1);free(src2);return 0; }

Makefile

CC = @echo " GCC $@"; $(CROSS)gccCROSS = arm-xmv2-linux- CFLAGS += -mcpu=cortex-a9 -mfloat-abi=softfp -mfpu=neon -mno-unaligned-access -fno-aggressive-loop-optimizations -flax-vector-conversions -fsigned-char -fopenmp CFLAGS += -std=gnu99 -Wall -O2TESTSOURCE = $(wildcard ./main.c) TESTTARGET = main.outTARGET = $(TESTTARGET) all:$(TARGET)$(TESTTARGET):$(CC) $(CFLAGS) -save-temps -o $(TESTTARGET) $(TESTSOURCE) -lstdc++ -lmclean:rm -f $(TESTTARGET)

效果對比

3.總結

  • demo中可以明顯看到程序執行耗時減少一半,效果非常明顯
  • neon只適用于重復運算,我們只需要找到那些具有重復運算的地方,然后使用neon進行加速
  • 第一次看到這些函數非常陌生,多去官網查幾次就熟悉了

總結

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

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