日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

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

编程问答

ARM SIMD 指令集:NEON 简介

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

ARM SIMD 指令集:NEON 簡介

    • 一、NEON 簡介
      • 1.1、NEON 簡介
      • 1.2、NEON 使用方式
      • 1.3、編譯器自動向量化的編譯選項
        • 1.3.1 Arm Compiler 中使能自動向量化
        • 1.3.2 LLVM-clang 中使能自動向量化
        • 1.3.3 GCC 中使能自動向量化
      • 1.4、NEON intrisics 指令在x86平臺的仿真
    • 二、NEON 數據類型和指令類型
      • 2.1、NEON 數據類型
      • 2.2、 NEON 指令類型
    • 三、NEON 指令簡介
      • 3.1、數據讀取指令(內存數據加載到寄存器)
      • 3.2、數據存儲指令(寄存器數據回寫到內存 )
      • 3.3、數據處理指令
        • 3.3.1 獲取寄存器的值
        • 3.3.2 設置寄存器的值
        • 3.3.3 加減乘除運算
        • 3.3.4 邏輯運算
        • 3.3.5 數據類型轉換
        • 3.3.6 寄存器數據重排
    • 四、NEON 進階
    • 五、參考連接


一、NEON 簡介

1.1、NEON 簡介

  • SIMD,即 single instruction multiple data,單指令流多數據流,也就是說一次運算指令可以執行多個數據流,從而提高程序的運算速度,實質是通過 數據并行 來提高執行效率
  • ARM NEON 是 ARM 平臺下的 SIMD 指令集,利用好這些指令可以使程序獲得很大的速度提升。不過對很多人來說,直接利用匯編指令優化代碼難度較大,這時就可以利用 ARM NEON intrinsic 指令,它是底層匯編指令的封裝,不需要用戶考慮底層寄存器的分配,但同時又可以達到原始匯編指令的性能。
    • NEON 是一種 128 位的 SIMD 擴展指令集,由 ARMv7 引入,在 ARMv8 對其功能進行了擴展(支持向量化運算),支持包括加法、乘法、比較、移位、絕對值 、極大極小極值運算、保存和加載指令等運算
    • ARM 架構下的下一代 SIMD 指令集為 SVE(Scalable Vector Extension,可擴展矢量指令),支持可變矢量長度編程,SVE 指令集的矢量寄存器的長度最小支持 128 位,最大可以支持 2048 位,以 128 位為增量
  • ARM NEON 技術的核心是 NEON 單元,主要由四個模塊組成:NEON 寄存器文件、整型執行流水線、單精度浮點執行流水線和數據加載存儲和重排流水線
  • ARM 基本數據類型有三種:字節(Byte,8bit)、半字(Halfword,16bit)、字(Word,32bit)
  • 新的 Armv8a 架構有 32 個 128bit 向量寄存器,老的 ArmV7a 架構有 32 個 64bit(可當作 16 個128bit)向量寄存器,被用來存放向量數據,每個向量元素的類型必須相同,根據處理元素的大小可以劃分為 2/4/8/16 個通道

1.2、NEON 使用方式

  • ARM 平臺提供了四種使用 NEON 技術的方式,分別為 NEON 內嵌函數(intrinsics)、NEON 匯編、NEON 開源庫和編譯器自動向量化
    • NEON 內嵌函數:類似于普通函數調用,簡單易維護,編譯器負責將 NEON 指令替換成匯編語言的復雜任務,主要包括寄存器分配和代碼調度以及指令集重排,來達到獲取最高性能的目標
    • NEON 匯編:匯編語言相對晦澀難懂,移植較難、不便于維護,但其 效率最高
    • NEON 開源庫:如 Ne10、OpenMAX、ffmpeg、Eigen3 和 Math-neon 等
    • 編譯器自動向量化:目前大多數編譯器都具有自動向量化的功能,將 C/C++ 代碼自動替換為 SIMD 指令。從編譯技術上來說,自動向量化一般包含兩部分:循環向量化(Loop vectorization)和超字并行向量化(SLP,Superword-Level Parallelism vectorization,又稱 Basic block vectorization)
      • 循環向量化:將循環進行展開,增加循環中的執行代碼來減少循環次數
      • SLP 向量化:編譯器將多個標量運算綁定到一起,使其成為向量運算
  • 編寫代碼時要加上頭文件:#include <arm_neon.h>,編譯時要加上相應的 編譯選項:LOCAL_CFLAGS += -mcpu=cortex-a53 -mfloat-abi=softfp -mfpu=neon-vfpv4 -O3

1.3、編譯器自動向量化的編譯選項

  • 目前支持自動向量化的編譯器有 Arm Compiler 6、Arm C/C++ Compiler、LLVM-clang 以及 GCC,這幾種編譯器間的相互關系如下表所示:

1.3.1 Arm Compiler 中使能自動向量化

  • 下文中 Arm Compiler 6 與 Arm C/C++ Compiler 使用 armclang 統稱,armclang 使能自動向量化配置信息如下表所示:

  • armclang 實現自動向量化示例:

# AArch32 armclang --target=arm-none-eabi -mcpu=cortex-a53 -O1 -fvectorize main.c# AArch64,O2 及以上優化等級默認啟用自動向量化 -fvectorize armclang --target=aarch64-arm-none-eabi -O2 main.c

1.3.2 LLVM-clang 中使能自動向量化

  • Android NDK 從 r13 開始以 clang 為默認編譯器,使用 Android NDK 工具鏈使能自動向量化配置參數如下表所示:
  • 在 CMake 中配置自動向量化方式如下:
# method 1 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O1 -fvectorize") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O1 -fvectorize")# method 2 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2")

1.3.3 GCC 中使能自動向量化

  • 在 gcc 中使能自動向量化配置參數如下:

  • 在不明確配置 -mcpu 的情況下,編譯器將使用默認配置(取決于編譯工具鏈時的選項設置)進行編譯,通常情況下 -mfpu 和 -mcpu 的配置存在關聯性,對應關系如下:

  • gcc 中實現自動向量化的編譯配置如下:

# AArch32 arm-none-linux-gnueabihf-gcc -mcpu=cortex-a53 -mfpu=neon -ftree-vectorize -O2 main.c# AArch64 aarch64-none-linux-gnu-gcc -mcpu=cortex-a53 -ftree-vectorize -O2 main.c

1.4、NEON intrisics 指令在x86平臺的仿真

  • 為了便于 NEON 指令從 ARM 平臺移植到 x86 平臺使用,Intel 提供了一套轉化接口 NEON2SSE,用于將 NEON 內聯函數轉化為 Intel SIMD(SSE) 內聯函數,大部分 x86 平臺 C/C++編譯器均支持 SSE,因此只需下載并包含接口頭文件 NEON_2_SSE.h,即可在x86平臺調試 NEON 指令代碼
  • x86 上模擬實現可參考:
    • NEON_2_SSE.h 是個好東西
    • https://github.com/intel/ARM_NEON_2_x86_SSE
    • https://github.com/christophe-lyon/arm-neon-tests
# 1、編程時加上頭文件 #include "NEON_2_SSE.h"# 2、編譯時加上如下編譯選項(debug) # gdb 調試時出現value optimized out 解決方法如下: # 由于 gcc 在編譯過程中默認使用 -O2 優化選項,希望進行單步跟蹤調試時,應使用 -O0 選項 set(CMAKE_C_FLAGS "-w -mfma -mavx512f -msse4 -msse4.1 -msse4.2 -O0") set(CMAKE_CXX_FLAGS "-w -mfma -mavx512f -msse4 -msse4.1 -msse4.2 -O0")

二、NEON 數據類型和指令類型

2.1、NEON 數據類型

  • NEON 向量數據類型是根據以下模式命名的:<type><size>x<number_of_lanes>_t,eg:int8x16_t 是一個16 通道 的向量,每個通道包含一個有符號 8 位整數
  • NEON 還提供了數組向量數據類型,命名模式如下:<type><size>x<number of lanes>x<length of array>_t,eg:int8x16x4_t 是一個長度為 4 的數組,每一個數據的類型為 int8x16_t
struct int8x16x4_t {int8x16_t val[4]; // 數組元素的長度范圍 2 ~ 4};

  • 下表列出了 16 個 D 寄存器上的向量數據類型及 16 個 Q 寄存器上的向量數據類型
  • D 寄存器一次能處理 8 個 u8 數據,Q 寄存器一次能處理 16 個 u8 數據
D寄存器(64-bit)Q寄存器(128-bit)
int8x8_tint8x16_t
int16x4_tint16x8_t
int32x2_tint32x4_t
int64x1_tint64x2_t
uint8x8_tuint8x16_t
uint16x4_tuint16x8_t
uint32x2_tuint32x4_t
uint64x1_tuint64x2_t
float16x4_tfloat16x8_t
float32x2_tfloat32x4_t
poly8x8_tpoly8x16_t
poly16x4_tpoly16x8_t

2.2、 NEON 指令類型

NEON指令的函數名組成格式:v<mod><opname><shape><flags>_<type> ,逐元素進行操作

  • v:vector 的縮寫,表示向量
  • mod:
    • q:表示飽和計算,int8x8_t vqadd_s8(int8x8_t a, int8x8_t b); // a 加 b 的結果做飽和計算
    • h:表示折半計算,int8x8_t vhsub_s8(int8x8_t a, int8x8_t b); // a 減 b 的結果右移一位
    • d:表示加倍計算,int32x4_t vqdmull_s16(int16x4_t a, int16x4_t b); // a 乘 b 的結果擴大一倍, 最后做飽和操作
    • r:表示舍入計算,int8x8_t vrhadd_s8(int8x8_t a, int8x8_t b); // 將 a 與 b 的和減半,同時做 rounding 操作, 每個通道可以表達為: (ai + bi + 1) >> 1
    • p:表示 pairwise 計算,int8x8_t vpadd_s8(int8x8_t a, int8x8_t b); // 將 a, b 向量的相鄰數據進行兩兩和操作
  • opname:表示具體操作,比如 add,sub 等
  • shape:
    • l:表示 long,輸出向量的元素長度是輸入長度的 2 倍,uint16x8_t vaddl_u8(uint8x8_t a, uint8x8_t b);
    • w:表示 wide,第一個輸入向量和輸出向量類型一樣,且是第二個輸入向量元素長度的 2 倍,uint16x8_t vsubw_u8(uint16x8_t a, uint8x8_t b);
    • n:表示 narrow,輸出向量的元素長度是輸入長度的 1/2 倍,uint32x2_t vmovn_u64(uint64x2_t a);
    • _high:AArch64專用,而且和 l/n 配合使用,當使用 l(Long) 時,表示輸入向量只有高 64bit 有效;當使用 n(Narrow) 時,表示輸出只有高 64bit 有效,int16x8_t vsubl_high_s8(int8x16_t a, int8x16_t b); // a 和 b 只有高 64bit 參與運算
    • _n:表示有標量參與向量計算,int8x8_t vshr_n_s8(int8x8_t a, const int n); // 向量 a 中的每個元素右移 n 位
    • _lane: 指定向量中某個通道參與向量計算,int16x4_t vmul_lane_s16(int16x4_t a, int16x4_t v, const int lane); // 取向量 v 中下標為 lane 的元素與向量 a 做乘法計算
  • flags:q 表示 quad word,四字,指定函數對 128 位 Q 寄存器進行操作,不帶 q 則對 64 位 D 寄存器進行操作
  • type:表示函數的參數類型(u8/16/32/64、s8/16/32/64、f16/32 等)
  • 正常指令:
    • 生成大小相同且類型通常與操作數向量相同的結果向量,結果大于 2n2^n2n 的除以 2n2^n2n 取余數,結果小于 0 的加上 2n2^n2n
    • eg: int8x8_t vadd_s8 (int8x8_t __a, int8x8_t __b)
  • 飽和指令:
    • 當超過數據類型指定的范圍則自動限制在該范圍內(結果大于 2n?12^n - 12n?1 的截斷到 2n?12^n - 12n?1 ,結果小于 0 的截斷到 0 ),函數中用 q 來標記(在 v 之后)
    • eg: int8x8_t vqsub_s8 (int8x8_t __a, int8x8_t __b)
  • 長指令:
    • 雙字向量操作數執行運算,生成四字向量的結果,所生成的元素一般是操作數元素寬度的兩倍,并屬于同一類型,函數中用 l 來標記,結果大于 2n2^n2n 的減去 2n2^n2n (一般不會),結果小于 0 的加上 2n2^n2n (可能出現)
    • eg:int16x8_t vaddl_s8 (int8x8_t __a, int8x8_t __b)
  • 寬指令:
    • 一個雙字向量操作數和一個四字向量操作數執行運算,生成四字向量結果。所生成的元素和第一個操作數的元素是第二個操作數元素寬度的兩倍,函數中用 w 來標記
    • eg:int16x8_t vaddw_s8 (int16x8_t __a, int8x8_t __b)
  • 窄指令:
    • 四字向量操作數執行運算,并生成雙字向量結果,所生成的元素一般是操作數元素寬度的一半,函數中用 hn 來標記
    • eg: int8x8_t vaddhn_s16 (int16x8_t __a, int16x8_t __b)

三、NEON 指令簡介

  • NEON 指令執行流程如下:
// 用 float 類型的 val 值,去初始化寄存器,值為 val float32x4_t vec = vdupq_n_f32(val);

3.1、數據讀取指令(內存數據加載到寄存器)

  • 順序讀取
// vld1 -> loads a vector from memory float32x2_t temp = vld1_f32(const float32_t * __a); // load 2 float32 64-bit float32x4_t temp = vld1q_f32(const float32_t * __a); // load 4 float32 128-bit
  • 交織讀取
// vld2 -> loads 2 vector from memory,vld3 vld4 the same as vld2 // 交叉存放: a1 a2 a3 a4 -> temp.val[0]:a1 a3 ; temp.val[1]:a2 a4 float32x2x2_t temp = vld2_f32 (const float32_t * __a); // load 4 float32 64-bit float32x4x2_t temp = vld2q_f32 (const float32_t * __a); // load 8 float32 128-bit

3.2、數據存儲指令(寄存器數據回寫到內存 )

  • 順序存儲
// vst1 -> stores a vector into memory void vst1_f32 (float32_t * ptr, float32x2_t temp); // store 2 float32 64-bit void vst1q_f32 (float32_t * ptr, float32x4_t temp); // store 4 float32 64-bit
  • 交織存儲
// vst2 -> stores 2 vector into memory,It interleaves the 2 vectors into memory. void vst2_f32 (float32_t * ptr, float32x2x2_t temp); // store 4 float32 64-bit void vst2q_f32 (float32_t * ptr, float32x4x2_t temp); // store 8 float32 64-bit

3.3、數據處理指令

3.3.1 獲取寄存器的值

// 從寄存器中訪問具體元素:extract a single lane (element) from a vector uint8_t vgetq_lane_u8(uint8x16_t vec, __constrange(0,15) int lane);

3.3.2 設置寄存器的值

// 設置寄存器具體元素值:set a single lane (element) within a vector. // 注意:返回值要用參數中的 vec 寄存器來接收 uint16x8_t vsetq_lane_u16(uint16_t value, uint16x8_t vec, __constrange(0,7) int lane); eg: vec = vsetq_lane_u16(111, vec, 5);// 設置寄存器所有元素的值(以某一個通道的值):Set all lanes to the value of one lane of a vector uint8x8_t vdup_lane_u8(uint8x8_t vec, __constrange(0,7) int lane) eg: vec = vdup_lane_u8(vec, 5); // 所有元素都設置成第五通道的值// 設置寄存器所有元素的值(以某一個固定的值) uint8x16_t vmovq_n_u8(uint8_t value); eg: uint8x16_t vec = vmovq_n_u8(5); // 所有元素都設置成 5

3.3.3 加減乘除運算

  • 加法
// 正常指令加法運算 int32x2_t vadd_s32(int32x2_t __a, int32x2_t __b);// 飽和指令加法,結果超出元素類型的最大值時,元素就取最大值;小于元素類型的最小值時,元素就取最小值 int32x2_t vqadd_s32(int32x2_t __a, int32x2_t __b);// 長指令加法運算,為了防止溢出,輸出向量長度是輸入的兩倍 int64x2_t vaddl_s32(int32x2_t __a, int32x2_t __b);// 向量半加:相加結果再除 2(向下取整),ri = (ai + bi) >> 1: int32x2_t vhadd_s32(int32x2_t __a, int32x2_t __b);// 向量舍入半加:相加結果再除 2,ri = (ai + bi + 1) >> 1: int32x2_t vrhadd_s32(int32x2_t __a, int32x2_t __b);// pairwise add,r0 = a0 + a1, ...,r3 = a6 + a7, r4 = b0 + b1, ...,r7 = b6 + b7 int8x8_t vpadd_s8(int8x8_t __a, int8x8_t __b);// long pairwise add, r0 = a0 + a1, ..., r3 = a6 + a7 int16x4_t vpaddl_s8(int8x8_t __a); // Long pairwise add and accumulate,r0 = a0 + (b0 + b1), ..., r3 = a3 + (b6 + b7) int16x4_t vpadal_s8(int16x4_t __a, int8x8_t __b);// 寬指令加法運算,第一個輸入向量的長度是第二個輸入向量長度的兩倍 int64x2_t vaddw_s32(int64x2_t __a, int32x2_t __b);// 窄指令加法,結果的類型大小是輸入類型大小的一半,待驗證??? int16x4_t vaddhn_s32(int32x4_t __a, int32x4_t __b);

  • 減法
// 正常減法運算 int32x4_t vsubq_s32(int32x4_t __a, int32x4_t __b);// 飽和指令減法,結果超出元素類型的最大值時,元素就取最大值 int32x2_t vqsub_s32 (int32x2_t __a, int32x2_t __b);// 長指令減法運算,為了防止溢出 int64x2_t vsubl_s32(int32x2_t __a, int32x2_t __b);// 向量半減:相減結果再除 2,ri = (ai - bi) >> 1 int32x2_t vhsub_s32 (int32x2_t __a, int32x2_t __b)// 寬指令減法運算,第一個元素寬度大于第二個 int64x2_t vsubw_s32(int64x2_t __a, int32x2_t __b);// 窄指令減法,結果的類型大小是輸入類型大小的一半 int16x4_t vsubhn_s32 (int32x4_t __a, int32x4_t __b);

  • 乘法
// ri = ai * bi,正常指令,逐元素相乘 int32x2_t vmul_s32 (int32x2_t __a, int32x2_t __b);// ri = ai * bi, 長指令, 為了防止溢出 int64x2_t vmull_s32 (int32x2_t __a, int32x2_t __b)// ri = ai * b,有標量參與向量運算 int32x2_t vmul_n_s32 (int32x2_t __a, int32_t __b);// ri = ai * b, 長指令, 為了防止溢出 int64x2_t vmull_n_s32 (int32x2_t __a, int32_t __b);// ri = ai * b[c] int32x2_t vmul_lane_s32 (int32x2_t __a, int32x2_t __b, const int __c)// ri = ai * b[c], 長指令,為了防止溢出 int64x2_t vmull_lane_s32 (int32x2_t __a, int32x2_t __b, const int __c);// ri = sat(ai * bi) 飽和指令,當結果溢出時,取飽和值 int32x2_t vqdmulh_s32 (int32x2_t __a, int32x2_t __b);
  • 乘加
// ri = ai + bi * ci,正常指令 int32x2_t vmla_s32 (int32x2_t __a, int32x2_t __b, int32x2_t __c)// ri = ai + bi * ci,長指令 int64x2_t vmlal_s32 (int64x2_t __a, int32x2_t __b, int32x2_t __c);// ri = ai + bi * c,正常指令,乘以標量 int32x2_t vmla_n_s32 (int32x2_t __a, int32x2_t __b, int32_t __c);// ri = ai + bi * c,長指令,乘以標量 int64x2_t vmlal_n_s32 (int64x2_t __a, int32x2_t __b, int32_t __c);// ri = ai + bi * c[d] int32x2_t vmla_lane_s32 (int32x2_t __a, int32x2_t __b, int32x2_t __c, const int __d);// ri = ai + bi * c[d] 長指令 int64x2_t vmlal_lane_s32 (int64x2_t __a, int32x2_t __b, int32x2_t __c, const int __d);// ri = ai + bi * ci 在加法之前,bi、ci相乘的結果不會被四舍五入 float32x2_t vfma_f32 (float32x2_t __a, float32x2_t __b, float32x2_t __c)// ri = sat(ai + bi * c) int64x2_t vqdmlal_n_s32 (int64x2_t __a, int32x2_t __b, int32_t __c);// ri = sat(ai + bi * c[d]) int64x2_t vqdmlal_lane_s32 (int64x2_t __a, int32x2_t __b, int32x2_t __c, const int __d);
  • 乘減
// ri = ai - bi * ci int32x2_t vmls_s32 (int32x2_t __a, int32x2_t __b, int32x2_t __c);// ri = ai - bi * ci 長指令,正常指令 int64x2_t vmlsl_s32 (int64x2_t __a, int32x2_t __b, int32x2_t __c);// ri = ai - bi * c,正常指令,乘以標量 int32x2_t vmls_n_s32 (int32x2_t __a, int32x2_t __b, int32_t __c);// ri = ai - bi * c,長指令,乘以標量 int64x2_t vmlsl_n_s32 (int64x2_t __a, int32x2_t __b, int32_t __c);// ri = ai - bi * c[d] int32x2_t vmls_lane_s32 (int32x2_t __a, int32x2_t __b, int32x2_t __c, const int __d);// ri = ai - bi * c[d] 長指令 int64x2_t vmlsl_lane_s32 (int64x2_t __a, int32x2_t __b, int32x2_t __c, const int __d); // ri = ai - bi * ci 在減法之前,bi、ci相乘的結果不會被四舍五入 float32x2_t vfms_f32 (float32x2_t __a, float32x2_t __b, float32x2_t __c);// ri = sat(ai - bi * c) int64x2_t vqdmlsl_n_s32 (int64x2_t __a, int32x2_t __b, int32_t __c);// ri = sat(ai - bi * c[d]) int64x2_t vqdmlsl_lane_s32 (int64x2_t __a, int32x2_t __b, int32x2_t __c, const int __d);
  • 倒數/平方根
// finds an approximate reciprocal of each element in a vector float32x2_t vrecpe_f32 (float32x2_t __a); // 注:vrecpe_type 計算倒數能保證千分之一左右的精度,如 1.0 的倒數為 0.998047 // 執行完如下語句后能提高百萬分之一精度 // float32x4_t recip = vrecpeq_f32(src); 此時能達到千分之一左右的精度,如 1.0 的倒數為 0.998047 // recip = vmulq_f32 (vrecpsq_f32 (src, rec), rec); 執行后能達到百萬分之一左右的精度,如1.0的倒數為0.999996 // recip = vmulq_f32 (vrecpsq_f32 (src, rec), rec); 再次執行后能基本能達到完全精度,如1.0的倒數為1.000000// performs a Newton-Raphson step for finding the reciprocal float32x2_t vrecps_f32 (float32x2_t a, float32x2_t b); float32x4_t vrecpsq_f32(float32x4_t a, float32x4_t b);// 近似平方根 float32x2_t vrsqrts_f32(float32x2_t a, float32x2_t b); float32x4_t vrsqrtsq_f32(float32x4_t a, float32x4_t b);
  • 取負
// vneg -> ri = -ai int32x2_t vneg_s32 (int32x2_t __a);

3.3.4 邏輯運算

  • 取整
/*--1、to nearest, ties to even--*/ float32x2_t vrndn_f32 (float32x2_t __a); /*--2、to nearest, ties away from zero--*/ float32x2_t vrnda_f32 (float32x2_t __a); /*--3、towards +Inf--*/ float32x2_t vrndp_f32 (float32x2_t __a);/*--4、towards -Inf--*/ float32x2_t vrndm_f32 (float32x2_t __a); /*--5、towards 0--*/ float32x2_t vrnd_f32 (float32x2_t __a);
  • 比較運算:注意返回類型為無符號整數類型
// 邏輯比較操作,結果為 true,則該元素的所有 bit 位被設置為 1;結果為 false,則該元素的所有 bit 位被設置為 0 // 注意返回類型為無符號整數類型// compares equal : vceq -> ri = ai == bi ? 1...1 : 0...0 uint32x2_t vceq_s32 (int32x2_t __a, int32x2_t __b); // compares greater-than or equal : vcge-> ri = ai >= bi ? 1...1:0...0 uint32x2_t vcge_s32 (int32x2_t __a, int32x2_t __b);// compares less-than or equal : vcle -> ri = ai <= bi ? 1...1:0...0 uint32x2_t vcle_s32 (int32x2_t __a, int32x2_t __b); // compares greater-than : vcgt -> ri = ai > bi ? 1...1:0...0 uint32x2_t vcgt_s32 (int32x2_t __a, int32x2_t __b);// compares less-than : vclt -> ri = ai < bi ? 1...1:0...0 uint32x2_t vclt_s32 (int32x2_t __a, int32x2_t __b);// 向量的絕對值比較 // compares absolute greater-than or equal : vcage -> ri = |ai| >= |bi| ? 1...1:0...0; uint32x2_t vcage_f32 (float32x2_t __a, float32x2_t __b); // compares absolute less-than or equal : vcale -> ri = |ai| <= |bi| ? 1...1:0...0; uint32x2_t vcale_f32 (float32x2_t __a, float32x2_t __b);// compares absolute greater-than : vcage -> ri = |ai| > |bi| ? 1...1:0...0; uint32x2_t vcagt_f32 (float32x2_t __a, float32x2_t __b);// compares absolute less-than : vcalt -> ri = |ai| < |bi| ? 1...1:0...0; uint32x2_t vcalt_f32 (float32x2_t __a, float32x2_t __b); // 向量與不等于零判斷 // vtst -> ri = (ai & bi != 0) ? 1...1:0...0; uint32x2_t vtst_s32 (int32x2_t __a, int32x2_t __b);
  • 絕對值
// Absolute : vabs -> ri = |ai| int32x2_t vabs_s32 (int32x2_t __a);// Absolute difference : vabd -> ri = |ai - bi| int32x2_t vabd_s32 (int32x2_t __a, int32x2_t __b);// Absolute difference and accumulate: vaba -> ri = ai + |bi - ci| int32x2_t vaba_s32 (int32x2_t __a, int32x2_t __b, int32x2_t __c);
  • 最大最小值
// vmax -> ri = ai >= bi ? ai : bi; 取向量元素中較大的那一個輸出 int32x2_t vmax_s32 (int32x2_t __a, int32x2_t __b);// vmin -> ri = ai >= bi ? bi : ai; int32x2_t vmin_s32 (int32x2_t __a, int32x2_t __b);// compares adjacent pairs of elements, 獲取相鄰對的最大值 // vpmax -> vpmax r0 = a0 >= a1 ? a0 : a1, ..., r4 = b0 >= b1 ? b0 : b1, ...; int32x2_t vpmax_s32 (int32x2_t __a, int32x2_t __b); // compares adjacent pairs of elements, 獲取相鄰對的最小值 // vpmin -> r0 = a0 >= a1 ? a1 : a0, ..., r4 = b0 >= b1 ? b1 : b0, ...; int32x2_t vpmin_s32 (int32x2_t __a, int32x2_t __b);
  • 移位運算:第二個參數是 int 型,參數均為 vector 的時候可為負數
// Vector shift left: vshl -> ri = ai << bi,如果 bi 是負數,則變成右移 // The bits shifted out of each element are lost uint16x8_t vshlq_u16 (uint16x8_t __a, int16x8_t __b); // 正常指令 uint16x8_t vrshlq_u16 (uint16x8_t __a, int16x8_t __b); // 正常指令結果 + 四舍五入 uint16x8_t vqshlq_u16 (uint16x8_t __a, int16x8_t __b); // 飽和指令截斷到 (0,65535) uint16x8_t vqrshlq_u16 (uint16x8_t __a, int16x8_t __b); // 飽和指令截斷到 (0,65535) + 四舍五入// Vector shift left by constant: vshlq -> ri = ai << b,如果 b 是負數,則變成右移 // The bits shifted out of the left of each element are lost uint16x8_t vshlq_n_u16(uint16x8_t a, __constrange(0,15) int b); // 正常指令 uint16x8_t vqshlq_n_u16(uint16x8_t a, __constrange(0,15) int b); // 飽和指令截斷到 (0,65535), ri = sat(ai << b);// Vector signed->unsigned rounding narrowing saturating shift right by constant uint8x8_t vqrshrun_n_s16 (int16x8_t __a, const int __b); // 移位后舍入// Vector shift right:可以通過左移傳入負數來實現// Vector shift left by constant: vshrq -> ri = ai >> b uint16x8_t vshrq_n_u16(uint16x8_t a, __constrange(1,16) int b); uint16x8_t vrshrq_n_u16(uint16x8_t a, __constrange(1,16) int b); // 右移累加,vsra -> ri = (ai >> c) + (bi >> c); uint16x8_t vsraq_n_u16(uint16x8_t a, uint16x8_t b, __constrange(1,16) int c); uint16x8_t vrsraq_n_u16(uint16x8_t a, uint16x8_t b, __constrange(1,16) int c);/*--Vector shift left and insert: vsli ->; The least significant bit in each element in the destination vector is unchanged. left shifts each element in the second input vector by an immediate value, and inserts the results in the destination vector. It does not affect the lowest n significant bits of the elements in the destination register. Bits shifted out of the left of each element are lost. The first input vector holds the elements of the destination vector before the operation is performed.--*/ uint16x8_t vsliq_n_u16 (uint16x8_t __a, uint16x8_t __b, const int __c);/*--Vector shift right and insert: vsri -> ; The two most significant bits in the destination vector are unchanged. right shifts each element in the second input vector by an immediate value, and inserts the results in the destination vector. It does not affect the highest n significant bits of the elements in the destination register. Bits shifted out of the right of each element are lost.The first input vector holds the elements of the destination vector before the operation is performed.--*/ uint16x8_t vsriq_n_u16 (uint16x8_t __a, uint16x8_t __b, const int __c);
  • 按位運算
// vmvn -> ri = ~ai int32x2_t vmvn_s32 (int32x2_t __a);// vand -> ri = ai & bi int32x2_t vand_s32 (int32x2_t __a, int32x2_t __b);// vorr -> ri = ai | bi int32x2_t vorr_s32 (int32x2_t __a, int32x2_t __b);// veor -> ri = ai ^ bi int32x2_t veor_s32 (int32x2_t __a, int32x2_t __b);// vbic -> ri = ~ai & bi int32x2_t vbic_s32 (int32x2_t __a, int32x2_t __b);// vorn -> ri = ai | (~bi) int32x2_t vorn_s32 (int32x2_t __a, int32x2_t __b);

3.3.5 數據類型轉換

// 浮點轉定點 // 在 f32 轉到 u32 時,是向下取整,且如果是負數,則轉換后為 0 uint32x4_t vcvtq_u32_f32(float32x4_t a); uint32x4_t vcvtq_n_u32_f32(float32x4_t a, __constrange(1,32) int b);// 定點轉浮點 float32x4_t vcvtq_f32_u32(uint32x4_t a); float32x4_t vcvtq_n_f32_u32(uint32x4_t a, __constrange(1,32) int b);// 浮點之間轉換 float16x4_t vcvt_f16_f32(float32x4_t a); // VCVT.F16.F32 d0, q0 float32x4_t vcvt_f32_f16(float16x4_t a); // 定點之間轉換 int16x8_t vmovl_s8 (int8x8_t a); int8x8_t vqmovn_s16 (int16x8_t a); int32x4_t vmovl_s16 (int16x4_t a); int16x4_t vqmovn_s32 (int32x4_t a);// 向量重新解釋類型轉換運算:將元素類型為 type2 的 vector 轉換為元素類型為 type1 的 vector // 將向量視為另一類型而不更改其值 float32x2_t vreinterpret_f32_u32 (uint32x2_t __a);

3.3.6 寄存器數據重排

  • 按索引重排
// vext -> 提取第二個 vector 的低端的 c 個元素和第一個 vector 的高端的剩下的幾個元素 // 如:src1 = {1,2,3,4,5,6,7,8}// src2 = {9,10,11,12,13,14,15,16}// dst = vext_s8(src1,src2,3)時,則dst = {4,5,6,7,8, 9,10,11} int8x8_t vext_s8 (int8x8_t __a, int8x8_t __b, const int __c);// vtbl1 -> 第二個vector是索引,根據索引去第一個vector(相當于數組)中搜索相應的元素 // 并輸出新的vector,超過范圍的索引返回的是 0 // 如:src1 = {1,2,3,4,5,6,7,8} // src2 = {0,0,1,1,2,2,7,8} // dst = vtbl1_u8(src1,src2)時,則dst = {1,1,2,2,3,3,8,0} int8x8_t vtbl1_s8 (int8x8_t __a, int8x8_t __b); // vtbl2 -> 數組長度擴大到2個vector // 如:src.val[0] = {1,2,3,4,5,6,7,8}// src.val[1] = {9,10,11,12,13,14,15,16}// src2 = {0,0,1,1,2,2,8,10}// dst = vtbl2_u8(src,src2)時,則 dst = {1,1,2,2,3,3,9,11} int8x8_t vtbl2_s8 (int8x8x2_t __a, int8x8_t __b); //vtbl3 vtbl4類似// vtbx1 -> 與vtbl1功能一樣,不過搜索到的元素是用來替換第一個vector中的元素, // 并輸出替換后的新vector,當索引超出范圍時,則不替換第一個vector中相應的元素。 int8x8_t vtbx1_s8 (int8x8_t __a, int8x8_t __b, int8x8_t __c); // vtbx2 vtbx3 vtbx4類似// vbsl -> Bitwise Select, 按位選擇,參數為(mask, src1, src2) // mask 的某個 bit 為1,則選擇 src1 中對應的 bit,為 0,則選擇 src2 中對應的 bit int8x8_t vbsl_s8 (uint8x8_t __a, int8x8_t __b, int8x8_t __c);
  • 反轉向量元素
// vrev -> 將vector中的元素位置反轉 // 如:src1 = {1,2,3,4,5,6,7,8} // dst = vrev64_s8(src1)時,則dst = {8,7,6,5,4,3,2,1} int8x8_t vrev64_s8 (int8x8_t __a); // 如:src1 = {1,2,3,4,5,6,7,8} // dst = vrev32_s8(src1)時,則dst = {4,3,2,1,8,7,6,5} int8x8_t vrev32_s8 (int8x8_t __a); // 如:src1 = {1,2,3,4,5,6,7,8} // dst = vrev16_s8(src1)時,則dst = {2,1,4,3,6,5,8,7} int8x8_t vrev16_s8 (int8x8_t __a);
  • 轉置
// vtrn -> 將兩個輸入 vector 的元素通過轉置生成一個有兩個 vector 的矩陣 // 如:src.val[0] = {1,2,3,4,5,6,7,8} // src.val[1] = {9,10,11,12,13,14,15,16} // dst = vtrn_u8(src.val[0], src.val[1])時, // 則 dst.val[0] = {1,9, 3,11,5,13,7,15} // dst.val[1] = {2,10,4,12,6,14,8,16} int8x8x2_t vtrn_s8 (int8x8_t __a, int8x8_t __b);
  • 交叉
// vzip_type: 將兩個輸入 vector 的元素通過交叉生成一個有兩個vector的矩陣 // 如:src.val[0] = {1,2,3,4,5,6,7,8} // src.val[1] = {9,10,11,12,13,14,15,16} // dst = vzip_u8(src.val[0], src.val[1])時, // 則dst.val[0] = {1,9, 2,10,3,11,4,12} // dst.val[1] = {5,13,6,14,7,15,8,16} int8x8x2_t vzip_s8 (int8x8_t __a, int8x8_t __b);
  • 反交叉
// vuzp_type: 將兩個輸入vector的元素通過反交叉生成一個有兩個vector的矩陣(通過這個可實現n-way 交織) // 如:src.val[0] = {1,2,3,4,5,6,7,8} // src.val[1] = {9,10,11,12,13,14,15,16} // dst = vuzp_u8(src.val[0], src.val[1])時, // 則dst.val[0] = {1,3,5,7,9, 11,13,15} // dst.val[1] = {2,4,6,8,10,12,14,16} int8x8x2_t vuzp_s8 (int8x8_t __a, int8x8_t __b);
  • 組合向量:將兩個 64 位向量組合為單個 128 位向量
// vcombine -> 將兩個元素類型相同的輸入 vector 拼接成一個同類型但大小是輸入vector兩倍的新vector。 uint8x16_t vcombine_u8(uint8x8_t low, uint8x8_t high);
  • 拆分向量:將一個 128 位向量拆分為 2 個 64 位向量
// 從寄存器中獲取低半部分元素 uint8x8_t vget_low_u8(uint8x16_t a);// 從寄存器中獲取高半部分元素 uint8x8_t vget_high_u8(uint8x16_t a);

四、NEON 進階

  • CPU優化技術 - NEON 開發進階:對齊問題解決

  • ARM 官方算子優化:https://github.com/ARM-software/ComputeLibrary

  • NCNN NEON 優化參考:包含常用算子 sigmoid/softmax/relu 等

  • OPENCV 第三方庫 carotene NEON 算子優化

  • NEON 使用建議:

    • 每次讀入的數據盡可能的占滿 128 位
    • 除法使用乘法進行代替,浮點計算使用定點加移位的方式進行
    • 合并算法種的一些系數,進行化簡
    • 算子進行融合,避免內存的多次讀寫
    • 使用多核多線程進行加速

五、參考連接

1、Neon Intrinsics各函數介紹(*****)
2、https://developer.arm.com/documentation(*****)
3、ARM Neon Intrinsics 學習指北:從入門、進階到學個通透(*****)
4、ARM NEON 技術之 NEON 基礎介紹(***)
5、移動端算法優化(******)
6、利用 ARM NEON intrinsic 優化常用數學運算(***)

總結

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

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

久久呀 | 91精品免费在线 | 91欧美日韩国产 | 特级西西444www高清大视频 | 99国产精品一区 | 免费一级特黄毛大片 | 一区三区视频在线观看 | www视频在线免费观看 | 中文字幕在线观看完整版 | 亚欧日韩成人h片 | 在线视频日韩精品 | 久久综合婷婷国产二区高清 | 国产精品女人久久久久久 | 亚洲午夜精品久久久 | 久草在线久 | 久久免费一 | 在线综合色| 在线看片视频 | 天天玩天天干天天操 | 超碰在线公开免费 | 欧美一级黄色片 | 成人久久国产 | 中文字幕一区二区三区四区 | 国产中文字幕在线观看 | 亚洲精品中文在线观看 | 男女全黄一级一级高潮免费看 | 91探花国产综合在线精品 | 亚洲成av人片在线观看www | 国产专区视频在线观看 | 免费亚洲电影 | 亚洲综合视频在线播放 | 激情综合五月天 | 中文字幕日韩无 | 中文字幕高清在线播放 | 久久高清免费观看 | 在线观看一区二区精品 | 狠狠网站 | 国产不卡毛片 | 午夜少妇一区二区三区 | 国产精品淫 | 激情综合站 | 青青河边草免费直播 | 国产一区国产精品 | 亚洲国产成人精品久久 | 五月婷婷六月丁香激情 | 久久精品9 | 久久久久久久久综合 | 久久图 | 成年人在线免费视频观看 | 欧美黑人xxxx猛性大交 | av丝袜天堂 | 99久久久久国产精品免费 | 久久高清| 美女在线免费观看视频 | 青青河边草免费观看 | 999久久a精品合区久久久 | 国产在线免费 | 免费在线国产视频 | 九九电影在线 | 中文字幕高清av | 国产视频一区二区在线 | 欧美专区日韩专区 | 亚州精品国产 | 亚洲禁18久人片 | 天天射天天 | 久久久亚洲精华液 | 日韩国产欧美在线视频 | 97电影网站 | 免费网站黄 | 夜夜夜精品 | 亚洲精品a区 | 91久久国产综合精品女同国语 | 精品国产精品国产偷麻豆 | 福利在线看片 | 国产人成看黄久久久久久久久 | 激情综合网婷婷 | 国产亚洲精品bv在线观看 | 色在线高清 | 久久久受www免费人成 | 久久精品视频免费播放 | 国产丝袜美腿在线 | 人人插人人干 | 我要色综合天天 | 人人天天夜夜 | 久久中文精品视频 | 中文字幕电影在线 | 人人精久 | 亚州精品在线视频 | 国产第一福利网 | 国产精品免费久久久久影院仙踪林 | 狠狠久久综合 | 国产精品青青 | 热re99久久精品国产99热 | 天天干夜夜夜操天 | 7799av| 欧美动漫一区二区三区 | 国产主播99 | 99精品热视频 | 久久精品男人的天堂 | 视频三区 | 久久久亚洲国产精品麻豆综合天堂 | 日韩欧美精品一区 | 久久精品视频国产 | 国产色爽 | 在线观看成人国产 | 国产人成免费视频 | 黄色在线观看污 | 日韩视频一区二区在线 | 国产精品自产拍在线观看蜜 | 精品欧美一区二区三区久久久 | 摸阴视频| 在线观看理论 | 天天插狠狠插 | 在线观看电影av | 四虎成人精品永久免费av | 免费影视大全推荐 | 亚洲国产成人精品在线观看 | 午夜av免费| 国产精品一区久久久久 | 99日精品| 日韩av网站在线播放 | 亚洲第一中文字幕 | 国产精品久久久久久久免费观看 | 一区二区在线不卡 | 在线视频观看亚洲 | 成年性视频 | 国产亚洲精品久久久久秋 | 国产精品福利久久久 | 韩国av永久免费 | 成人av影院在线观看 | 中文字幕亚洲字幕 | 人人干人人添 | 狠狠躁18三区二区一区ai明星 | 国产精品乱码久久久 | 日韩免费在线 | 99精品视频免费观看视频 | 一区二区三区免费在线观看视频 | 免费在线a| a在线播放| 国产丝袜在线 | 国产中文字幕亚洲 | 日韩精品观看 | 久久久麻豆视频 | 久久九九精品 | 丁香婷婷在线观看 | 狠狠色丁香婷婷综合橹88 | 波多野结衣视频在线 | 超碰97人人干 | 欧美日韩国产二区 | 91av蜜桃 | 91精品国产九九九久久久亚洲 | av在线永久免费观看 | 中文字幕在线观看一区 | 国产精品视频一二三 | 亚洲国产精品久久 | 久二影院 | 91chinese在线 | 在线视频一二三 | 久久6精品 | 久草视频99| 亚洲九九精品 | 欧美性大战久久久久 | 欧美在线一二 | 欧美色一色 | 麻豆传媒一区二区 | 天堂av在线网 | 五月天综合网站 | 欧美午夜寂寞影院 | 久草www| 欧美a免费 | 在线三级av | 91热爆在线观看 | 91porny九色91啦中文 | 国产成人精品一区二区三区 | 99久久久久国产精品免费 | 日韩免费播放 | 99精品色 | 欧美ⅹxxxxxx| 久久精品之 | 欧美一级淫片videoshd | 久久在线播放 | 欧美午夜精品久久久久久浪潮 | 久久y| 黄色在线看网站 | 日本成人免费在线观看 | 国产精品久久艹 | 99这里有精品 | 好看av在线 | 免费精品国产va自在自线 | 黄色片免费电影 | 国产在线污 | 午夜久久视频 | 欧美精品久久久久久久久久丰满 | 日韩一级片大全 | 国产男女爽爽爽免费视频 | 麻豆视频免费播放 | 欧美日韩在线播放一区 | 97精品国产aⅴ | 婷婷色站 | 美女网站视频免费黄 | 91福利社区在线观看 | 久久久激情网 | 亚洲欧美一区二区三区孕妇写真 | 日本在线精品视频 | 亚洲人成精品久久久久 | 一区二区三区四区五区在线视频 | 免费观看9x视频网站在线观看 | 狠狠色丁香久久婷婷综合五月 | 日韩精品久久一区二区 | 日韩中文在线电影 | 2019中文 | 一级a性色生活片久久毛片波多野 | 99视频偷窥在线精品国自产拍 | 成年人视频免费在线播放 | 国产视频1区2区3区 久久夜视频 | 91一区一区三区 | 六月天综合网 | 五月婷婷激情五月 | 欧美另类网站 | 久久精品激情 | 久久国产精品免费一区二区三区 | 国产高清视频在线免费观看 | 精品久久久久久亚洲 | 91人人射| 五月综合激情婷婷 | 天天色棕合合合合合合 | 色噜噜狠狠狠狠色综合 | 成人在线你懂得 | 久久影视一区 | 国产精品美女久久久久久久久久久 | 香蕉影院在线 | 在线视频区 | 国产精品久久久久永久免费观看 | www.国产毛片 | 中文字幕亚洲精品日韩 | 在线观看韩日电影免费 | 麻豆激情电影 | 国产成人精品一区二区三区免费 | 成人免费91| av线上免费看 | 国产免费观看高清完整版 | 欧美日韩国产一二三区 | 久精品视频 | 亚洲国产精品一区二区久久hs | 欧美精品一二 | 国产一级在线观看 | 一区二区观看 | 色视频成人在线观看免 | 最近中文字幕完整视频高清1 | 久久国产99 | 亚洲国产美女久久久久 | 尤物97国产精品久久精品国产 | 五月婷婷六月丁香激情 | 成人欧美一区二区三区在线观看 | 精品一区二区日韩 | 九九色在线观看 | 波多野结衣精品 | 日本中文在线播放 | 婷婷色综合色 | 一级欧美黄 | 成人午夜电影在线播放 | 一区二区三区在线观看免费视频 | www.国产高清 | 国产成人在线观看 | 国产成人精品在线播放 | 麻豆视频在线播放 | 天天插伊人 | 天天做天天射 | 激情五月看片 | 国产99久久久国产 | 天天干天天草 | 高清av在线 | 一本大道久久精品懂色aⅴ 五月婷社区 | 精品视频一区在线观看 | 国产精品久久久久久久久毛片 | 亚洲成人免费在线观看 | 久久中文字幕在线视频 | 欧美国产一区在线 | 福利一区二区三区四区 | 国产精品大全 | 婷婷在线免费视频 | 国产原创在线观看 | 亚洲精品av中文字幕在线在线 | 国产精品久久电影观看 | 日韩av午夜在线观看 | 日本在线观看一区二区 | 99久久成人 | 黄色成人小视频 | 亚洲五月花 | 久久天 | 日韩在线电影观看 | 狠狠色噜噜狠狠狠狠2022 | 中文字幕在线播放av | 99久久精品久久亚洲精品 | 女人18片毛片90分钟 | 99一区二区三区 | 江苏妇搡bbbb搡bbbb | 狠狠色丁香婷婷综合视频 | 激情综合国产 | 最新午夜电影 | 久久久久久久久毛片精品 | 久久女教师 | 日韩丝袜在线观看 | 国产精品久久久久久久午夜片 | 99久久日韩精品视频免费在线观看 | 成人免费在线看片 | 国产在线欧美日韩 | 日本三级不卡视频 | 欧美黄色特级片 | 亚洲成人资源在线观看 | 97色se| 日韩在线观看第一页 | www久久| 国产久视频| 黄色国产精品 | 播五月婷婷 | av中文字幕免费在线观看 | 狠狠操狠狠干2017 | 黄色av一区二区 | 精品久久久久久一区二区里番 | 亚洲第一色 | 国产三级在线播放 | 色综合久久久久综合 | 这里只有精品视频在线 | 色婷婷中文 | 国产亚洲精品久久久久5区 成人h电影在线观看 | 天堂av网在线 | 91c网站色版视频 | 波多野结衣综合网 | 在线 国产一区 | 国产精品第三页 | 久久久精品高清 | 99久久99| 波多野结衣电影一区二区 | 久久久久久久av麻豆果冻 | 久久手机视频 | 国产在线观看中文字幕 | 全久久久久久久久久久电影 | 久久精品国产成人 | 黄色国产在线 | 99久久99久久精品 | 91精品国产综合久久福利不卡 | 国产美女久久 | av电影在线不卡 | 蜜臀av免费一区二区三区 | 有码中文字幕在线观看 | 狠狠操导航 | 五月天婷婷在线观看视频 | 伊人资源站| 国产一区二区中文字幕 | 成人资源站 | 精品成人久久 | 免费av片在线 | 日韩精品免费在线 | 99日精品 | 最近免费观看的电影完整版 | 91精品国自产拍天天拍 | 最新黄色av网址 | 九九热精品视频在线播放 | 精品一区在线 | 欧美精品一区在线 | 久草视频视频在线播放 | 一区二区精 | 日韩精品在线视频免费观看 | 久艹在线观看视频 | 日韩有码第一页 | 日韩精品久久中文字幕 | 亚洲精品国偷自产在线91正片 | 精品一区二区三区电影 | 成人免费毛片aaaaaa片 | 亚洲精品久久视频 | 国产看片网站 | 久久久久日本精品一区二区三区 | 国产剧情一区在线 | 日本在线视频一区二区三区 | 岛国大片免费视频 | 日韩中文在线视频 | 五月激情六月丁香 | 国产精品99久久久久久小说 | 美女一级毛片视频 | 五月综合网 | 五月婷婷色丁香 | 久久免费成人精品视频 | adn—256中文在线观看 | 色窝资源 | 成人99免费视频 | 婷婷久久综合九色综合 | 激情久久伊人 | 在线观看日韩中文字幕 | 中文字幕在线人 | 六月丁香综合网 | 丁香五月缴情综合网 | 男女激情片在线观看 | 成年人毛片在线观看 | 激情视频免费在线 | 国产高清视频免费最新在线 | 婷婷婷国产在线视频 | 亚洲免费激情 | 久久中文字幕视频 | 激情五月婷婷激情 | 国产精品久久久久久麻豆一区 | 欧美精品亚州精品 | 国产在线更新 | 中文字幕免费看 | 国产美女被啪进深处喷白浆视频 | 久久国内精品99久久6app | 精品一二三四五区 | 91丨九色丨高潮 | 伊人国产女| 91免费的视频在线播放 | 久久久精品 | 久久国产麻豆 | 91日韩在线播放 | 在线亚洲天堂网 | 国产亚洲精品bv在线观看 | 成人超碰97 | 精品一区二区免费 | 久久99久久99精品中文字幕 | 中文资源在线播放 | 久久久免费 | 免费看的国产视频网站 | 国内精品在线看 | 欧美一级特黄aaaaaa大片在线观看 | 国产精品久久久视频 | www国产亚洲精品久久网站 | 91精品国产91久久久久久三级 | 精品一区二区影视 | 国产精品 中文在线 | 国产精品一区二区免费 | 人人爱人人射 | 国产成人精品久久久 | 欧美极品在线播放 | 免费在线成人av | 免费看的黄色片 | 欧美精品在线观看 | 丁香六月色 | 久久男女视频 | 欧美国产一区在线 | 精品久久久久久综合 | 久久99免费视频 | 欧美精品久久久久久久久久久 | www.五月天 | 亚洲砖区区免费 | 国产伦精品一区二区三区高清 | 免费在线黄网 | 欧美日在线 | 一区 二区 精品 | 国产精品久久久av久久久 | 亚洲男女精品 | 国产又粗又猛又爽 | 久久精品亚洲综合专区 | 97福利在线观看 | 中文字幕 国产专区 | 亚洲一区动漫 | 久久久久久久免费观看 | 久久久免费看片 | 精品一区二区在线免费观看 | 国产日本亚洲 | 波多野结衣在线观看一区二区三区 | 国产成年人av | 午夜精品999 | 99视频在线观看视频 | 91成人观看 | 国产区精品区 | 久操综合| 国内精品久久久久久久久久 | 激情视频二区 | 毛片视频网址 | 一区二区免费不卡在线 | 欧美一区二区免费在线观看 | 91免费网| 亚洲精品66| 国产又粗又猛又色又黄网站 | 成年人在线观看网站 | 99草视频| 久热av| 天天综合人人 | 国产高清在线免费观看 | 天天干天天摸天天操 | 99久久久久久 | 成人午夜黄色影院 | 黄色片网站免费 | 精品在线99| 久久精品—区二区三区 | 日本激情中文字幕 | 国产乱对白刺激视频不卡 | 一区二区伦理电影 | 午夜黄色一级片 | 久久亚洲私人国产精品 | 国产精久久久久久妇女av | 69国产盗摄一区二区三区五区 | 伊人超碰在线 | 在线观看 国产 | 91麻豆精品国产91久久久更新时间 | 中文av资源站 | 91中文在线观看 | 91在线区 | 97爱爱爱| 综合国产在线观看 | 国产精品日韩欧美一区二区 | 国产免费看 | 免费看片网站91 | 精品久久精品久久 | 久久网页 | 亚洲最新在线 | 成年人国产精品 | 天天综合天天综合 | 欧美日韩中文字幕综合视频 | 日韩一区二区三区在线看 | 亚洲国内精品在线 | 综合色亚洲 | 天天操人| 美女视频黄色免费 | 亚洲第一区在线播放 | 中文字幕超清在线免费 | 欧洲精品视频一区 | 不卡视频一区二区三区 | 国产亚洲精品成人av久久ww | 国产最新福利 | 精品一区二区电影 | 免费网站黄 | 欧美日韩一区二区三区在线观看视频 | 在线观看国产中文字幕 | 国产一级免费在线观看 | 精品免费观看 | 日韩在线免费 | 日本三级人妇 | 国产黄色av网站 | www色com| 色a网 | 99久久精品国产观看 | av免费在线网站 | 欧美日韩精品在线观看视频 | 色婷婷视频网 | 色婷五月 | 久久永久免费视频 | 国产一卡久久电影永久 | 久久这里只有精品首页 | 久久久久久麻豆 | 97在线观看视频国产 | 狠狠色狠狠色综合日日92 | 天天色棕合合合合合合 | 国产日韩欧美在线一区 | 国产在线色视频 | 天堂在线视频中文网 | www.干| 在线电影91| 免费毛片一区二区三区久久久 | av电影在线观看完整版一区二区 | 国产精品黄网站在线观看 | 丁香久久五月 | 特级黄录像视频 | 91在线视频观看免费 | 成人av免费在线播放 | 国产 视频 高清 免费 | 成人h动漫精品一区二 | www.国产在线视频 | 精品福利国产 | 啪啪凸凸 | 精品免费在线视频 | 中文字幕成人av | 18av在线视频 | 国产精品免费一区二区三区在线观看 | 91精品国自产拍天天拍 | 91av在线免费视频 | 91九色精品女同系列 | 色哟哟国产精品 | 俺要去色综合狠狠 | 婷婷去俺也去六月色 | 欧美午夜性| 狠狠狠色狠狠色综合 | 国产在线播放一区 | 国产高清在线观看av | 久草网在线观看 | 日韩精品免费一区二区在线观看 | 在线观看视频在线 | 欧美做受高潮电影o | 最近日本中文字幕a | 成人国产精品久久久久久亚洲 | 日本一区二区高清不卡 | 中文字幕视频播放 | 亚洲成年人在线播放 | 国产精品毛片一区视频播不卡 | 久久久久久免费毛片精品 | 欧美视频一区二 | 欧美在线91 | 视频在线亚洲 | 国产精品情侣视频 | 久久久久国产精品厨房 | 国产男男gay做爰 | 欧美激情视频一区二区三区 | 五月婷婷一区二区三区 | 免费三级黄色 | 欧美日韩视频在线 | 麻豆网站免费观看 | 日韩免费不卡视频 | 91精品欧美 | 黄av资源 | 成 人 黄 色 视频免费播放 | 韩国av免费观看 | 欧美性色综合 | 亚洲综合导航 | 伊人婷婷 | 九九热1| 久久亚洲美女 | 成人日批视频 | 欧美午夜性生活 | 国产精品美女视频网站 | 精品少妇一区二区三区在线 | 欧美激情视频一区 | 亚洲视频,欧洲视频 | 爱射综合 | 337p欧美 | 日韩在线免费视频 | 亚洲欧美日韩中文在线 | 久久久久成人精品免费播放动漫 | 国产69精品久久app免费版 | 日韩在线观看你懂的 | 亚洲一区二区视频在线 | 2017狠狠干 | 午夜视频在线观看一区二区三区 | 国产成人精品一区二区三区 | 欧美二区在线播放 | 成人黄大片视频在线观看 | 在线观看午夜av | 一本一道久久a久久综合蜜桃 | 日韩精品免费一区二区在线观看 | 激情综合五月婷婷 | 日韩最新在线 | 日韩在线视频网站 | 一级黄色片网站 | 国内视频| 免费网址你懂的 | 91视频免费网址 | 日韩免费中文字幕 | 97超碰在线久草超碰在线观看 | 91丨九色丨蝌蚪丨对白 | 色综合久久综合网 | 久久精品一区二区三区中文字幕 | 国内亚洲精品 | 日日夜夜爱 | 国产精品麻豆果冻传媒在线播放 | 日本午夜免费福利视频 | 国产精品久久久久久欧美 | 香蕉视频一级 | 久草爱 | 国产精品av在线 | 精品福利在线视频 | 午夜av一区 | 免费在线观看一区 | 天天操月月操 | 色综合久久中文字幕综合网 | 精品免费在线视频 | 超碰97成人 | 美女免费黄网站 | 狠狠色丁香婷婷综合最新地址 | 最近2019中文免费高清视频观看www99 | 国产三级国产精品国产专区50 | 三级黄色免费片 | 国产裸体永久免费视频网站 | 欧美一区成人 | 成人国产精品入口 | 久久伊人五月天 | 天天草天天摸 | 精品国模一区二区 | 欧美精品乱码久久久久 | 四虎在线影视 | 天天碰天天操视频 | 天天操天天艹 | 亚洲精品在线观看中文字幕 | 久草视频免费看 | 国内精品亚洲 | 久久精品欧美日韩精品 | 国产精品美女久久久久久2018 | 日韩系列 | 婷婷在线综合 | 久草免费在线视频观看 | 激情一区二区三区欧美 | 天天干,天天射,天天操,天天摸 | 国内精品久久久久影院一蜜桃 | 久久久久久国产精品亚洲78 | 亚洲精品国产精品国自产在线 | 欧美xxxxx在线视频 | 日本激情视频中文字幕 | 在线免费观看不卡av | 在线观看视频免费播放 | 国模视频一区二区 | 日韩免费一区二区三区 | 国产中文字幕一区二区 | 国产精品久久久久久久久久99 | 69国产盗摄一区二区三区五区 | 久久精品国产美女 | 一区二区视频在线看 | 丝袜美女视频网站 | 精品国产一区二区三区久久久蜜月 | 中文国产字幕 | 成人精品999 | 91九色porny在线 | 草久在线视频 | 国产直播av| 亚洲成人网在线 | 色婷婷激婷婷情综天天 | 国产精品日韩欧美一区二区 | 成年人三级网站 | 成人久久18免费 | 午夜精品久久久久久久99婷婷 | 久久久久久久久久久久亚洲 | 国产亚洲精品久久久久久久久久久久 | 免费观看的av | 精品久久精品久久 | 香蕉视频在线免费看 | 天天爽夜夜爽人人爽曰av | 久久小视频 | av高清免费在线 | 亚洲男男gⅴgay双龙 | 中文字幕一区二区三区视频 | 五月婷在线播放 | 日批视频国产 | 国产一级精品视频 | 中文字幕一区二区三区四区久久 | 免费精品 | 色综合天天综合网国产成人网 | 国产精品私人影院 | 久久精品99视频 | 在线成人免费av | 99综合电影在线视频 | av在线成人 | 免费久久片| 久久精品在线免费观看 | 玖玖999| 亚洲精品国产日韩 | 三级小视频在线观看 | 日韩欧美精品在线 | www.天天干.com | 碰超在线 | 亚洲无在线 | 久久96国产精品久久99漫画 | 中文字幕精品一区久久久久 | 亚洲码国产日韩欧美高潮在线播放 | 久久久伊人网 | 美女视频黄是免费的 | 欧美怡红院视频 | 91精品久久久久久粉嫩 | 91完整视频 | 久久久久久久久久久久国产精品 | 麻豆国产视频下载 | 一区二区不卡视频在线观看 | 国产一区二区不卡视频 | 欧美在线视频一区二区 | 久久国产精品久久w女人spa | 日日干视频 | 91视频在线网址 | 最新99热| 日韩精品专区在线影院重磅 | 视频直播国产精品 | 久久久久久久久久久成人 | 午夜精品中文字幕 | 免费在线观看成人 | 天天操狠狠操 | 国产69精品久久久久久久久久 | 激情黄色一级片 | 91大神免费在线观看 | 99综合影院在线 | 成人久久久电影 | www.av免费 | 国产91精品看黄网站在线观看动漫 | 色五月情 | 精品欧美乱码久久久久久 | 国产一级二级在线播放 | 九月婷婷人人澡人人添人人爽 | 免费视频在线观看网站 | 婷婷.com| 五月开心婷婷 | 在线视频观看亚洲 | 亚洲精品一区二区三区新线路 | 日产乱码一二三区别在线 | 亚洲天堂网视频 | 国产精品黄网站在线观看 | 国产在线a | 欧美动漫一区二区三区 | 久热免费 | 一级黄网 | 国产麻豆电影在线观看 | 日本成人中文字幕在线观看 | 精品美女在线观看 | 国产高清av免费在线观看 | 日韩三区在线观看 | 日韩国产精品久久久久久亚洲 | 在线观看完整版免费 | 色a4yy| 综合久久一本 | 久久久精品欧美 | 精品美女久久久久 | 精品少妇一区二区三区在线 | 综合网伊人 | 夜夜操综合网 | 国产精品亚洲成人 | 亚洲干视频在线观看 | 精品国产aⅴ麻豆 | 久久麻豆视频 | 国产福利午夜 | 国色天香在线观看 | 黄色av一区二区 | 亚洲人视频在线 | 超碰激情在线 | 91精品国产综合久久久久久久 | 99r精品视频在线观看 | 九九热免费在线观看 | 天天干夜夜爱 | 久久不卡av | 狠狠伊人| 日韩在线视频观看免费 | 国产999视频| 九九免费在线视频 | 久久午夜鲁丝片 | 97色婷婷 | 欧美99热 | 久久婷婷色 | 99在线观看 | 亚洲区另类春色综合小说 | 日韩69视频 | 精品999在线观看 | 成人永久在线 | 久久国产露脸精品国产 | 一级特黄aaa大片在线观看 | 丰满少妇在线观看 | 国产午夜影院 | www久久久久 | 天天爽夜夜爽人人爽曰av | 精品一区二区在线免费观看 | 国产精品视频全国免费观看 | 欧美一区二视频在线免费观看 | 国产99黄| 成人久久免费视频 | 日本中文字幕在线免费观看 | 精品久久久久一区二区国产 | 国产高清绿奴videos | 色婷婷成人网 | 欧美综合国产 | 久久99热这里只有精品 | 婷婷亚洲综合 | 日韩一区二区在线免费观看 | 五月婷婷深开心 | 精品国产一区二区三区免费 | 一级久久精品 | 久久精品在线 | 日本免费久久高清视频 | 中文字幕网址 | 国产亚洲aⅴaaaaaa毛片 | 久久久久日本精品一区二区三区 | 国产黄色在线网站 | 久久人人97超碰精品888 | 国产亚洲精品久久 | 婷婷丁香色综合狠狠色 | 国产永久网站 | 最近高清中文在线字幕在线观看 | 日韩电影在线观看一区二区三区 | 国产精品久久久久久久婷婷 | 9ⅰ精品久久久久久久久中文字幕 | 热久久免费视频精品 | 黄色影院在线免费观看 | 日韩精品影视 | 日本三级国产 | 免费黄色a级毛片 | 亚洲理论电影网 | 久久爱资源网 | 精品亚洲免费 | 国产精品porn | 开心色插 | 久久精品欧美日韩精品 | 精品国产一区二区三区免费 | 69视频国产 | 色狠狠久久av五月综合 | 国产美女精品在线 | 亚洲撸撸 | 久久久色| 国产精品 国产精品 | 久草综合在线观看 | 国产午夜不卡 | 欧美一级免费黄色片 | 欧洲亚洲精品 | av观看在线观看 | 玖玖在线观看视频 | 五月婷婷在线视频观看 | 国产一二区精品 | 日韩电影在线观看一区 | 欧美日韩在线视频一区二区 | 欧美一二三专区 | 精品国模一区二区三区 | 日女人免费视频 | 日韩精品欧美专区 | 亚洲综合视频在线播放 | 一区二区三区免费在线观看视频 | 黄色在线观看www | 九九视频在线 | 五月天久久久 | 国产亚洲欧美精品久久久久久 | 亚洲视频在线看 | 可以免费观看的av片 | 日韩欧美精品在线视频 | 99久久精品免费看国产 | 天天色综合天天 | 在线欧美日韩 | 亚州中文av | 欧美日韩亚洲在线 | 国产精品永久免费观看 | 免费在线一区二区 | 在线国产一区二区三区 | 成人午夜精品久久久久久久3d | 国产+日韩欧美 | 97超碰人人模人人人爽人人爱 | 国产精品一区免费看8c0m | 在线视频黄 | 日韩国产精品久久久久久亚洲 | 久久国产精品99精国产 | 久久99精品国产91久久来源 | 婷婷五月情 | 九九免费在线视频 | 精品999在线 | 性色av免费看 | 久草在| 久久视频在线观看免费 | 狠狠操狠狠干天天操 | 国产精品毛片久久久久久久久久99999999 | 国内精品久久久久影院优 | 久久九九国产视频 | 亚洲精品视频网址 | 亚洲日本中文字幕在线观看 | 国产精品国产三级国产不产一地 | 又黄又爽的视频在线观看网站 | 99这里只有精品视频 | 日韩精品久久久 | 久久久综合香蕉尹人综合网 | 亚洲精品一区中文字幕乱码 | 亚洲精品国产精品国 | 久久无码精品一区二区三区 | 国产精品久久久久久久久久久免费 | 国产91在线观 | 成人动漫视频在线 | 国产一区二区三区高清播放 | www.99av| 色视频国产直接看 | 亚洲综合小说电影qvod | 99福利片 | 天天曰夜夜爽 | 久久久免费网站 | 免费视频99 | 91麻豆高清视频 | 欧美va电影| 手机在线观看国产精品 | 操操操天天操 | 日韩免费高清 | 天天干婷婷 | 激情网色 | 日本中文字幕高清 | 在线 视频 一区二区 | 欧美日韩免费视频 | 韩国视频一区二区三区 | 亚洲欧美日韩中文在线 | 国产精品国内免费一区二区三区 | 手机成人av | 亚洲精品综合一二三区在线观看 | 久久久精品福利视频 | 91视频 - v11av| 日韩免费视频网站 | 亚洲国产网站 | 国产精品视频 | 韩国在线一区 | 国产精品毛片一区二区在线 | 久久亚洲精品国产亚洲老地址 | 午夜三级在线 | 精品国产乱码久久久久久1区2匹 | 91精品免费看 | 日韩三级久久 | 狠狠躁夜夜躁人人爽视频 | 在线观看免费 | 免费观看国产视频 | 久久综合九色九九 | 成人性生活大片 | 国产精品毛片久久久久久 | 久久久观看 | 欧美亚洲一级片 | 欧美性春潮 | 精品99久久 | 久久久久国产成人精品亚洲午夜 | 免费99| 亚洲综合激情五月 | 97人人添人澡人人爽超碰动图 | 精品国产一区二区三区久久久久久 | 成人av中文字幕在线观看 | 国内精品久久久久影院一蜜桃 | 黄色a级片在线观看 | 91精品视频在线 | 欧美了一区在线观看 | 亚洲黄色影院 | 六月激情丁香 | 日韩免费福利 | 2019中文在线观看 |