NEON 常用函数讲解

news/2024/10/30 13:33:54/

目录

一、基本的加载存储操作

        1. vld1q_f32

2.vst1q_f32

 3.vld2q_f32 

 4.vst2q_f32

5.vld3q_f32

6.vst3q_f32

7.vld4q_f32, vst4q_f32

二、特殊操作 

 1.vdupq_n_f32

2.vzipq_f32 

 3.vuzpq_f32

4.vcombine_f32 

5. vget_low_f32

6. vget_high_f32

7. vtrnq_f32

8. vextq_f32

9.vget_lane_f32

10. vsetq_lane_f32

11.vtbl1_s8

12.vrev16_s8

 三、基本数据类型的转换

1.vcvtq_u32_f32

2.vcvtq_s32_f32 

3. vcvtq_f32_s32

4.vcvtq_f32_u32

四、基本比较运算

1.vceq_f32  

2.vceqq_f32

3. vmaxq_f32

4. vminq_f32

5.vpmax_s8

6.vpmin_s8

五、基本的位运算

 1.vclsq_s32

 2.vclzq_s32

3.vcnt_s8

4.vmvn_s8 

5.vqneg_s8 

6. vqshl_s8

六、基本的逻辑运算

 七、基本的算术运算

1.vadd_f32

2.vaddq_f32

3.vpadd_f32

3.vmulq_f32

4. vmlaq_f32

 

5.vmlaq_lane_f32

 

6.vmaxq_f3

 7.vrecpeq_f32

 8.vrsqrteq_f32


令初始数据为:
float d0[4] = {0.f, 1.f, 2.f, 3.f};
float d1[4] = {4.f, 5.f, 6.f, 7.f};
float d2[4] = {8.f, 9.f, 10.f, 11.f};
float d3[4] = {12.f, 13.f, 14.f, 15.f};

一、基本的加载存储操作

1. vld1q_f32

float32x4_t q0 = vld1q_f32(d0); // 加载 d0 地址起始的 4 个 float 数据到 q0

2.vst1q_f32

vst1q_f32(d1, q0);// 将 q0 中 4 个 float32,赋值给以 d1 为起始地址的 4 个 float32

 3.vld2q_f32 

float d4[8]= {1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f};
float32x4x2_t ret = vld2q_f32 (d4);

注意,此时在寄存器是交错读取的!

 4.vst2q_f32

vst2q_f32 (d4, ret);

注意,由于寄存器是交错存储的,所以内存保持不变!

5.vld3q_f32

float d5[12] = {1.f, 2.f, 3.f, 4.f,
5.f, 6.f, 7.f, 8.f,
9.f, 10.f, 11.f, 12.f};
float32x4x3_t f = vld3q_f32 (d5);

6.vst3q_f32

vst3q_f32 (d5, f);

7.vld4q_f32, vst4q_f32

略 

二、特殊操作 

 1.vdupq_n_f32

float32x4_t res = vdupq_n_f32(0.f); // 存储的四个 float32 都初始化为 0

2.vzipq_f32 

float32x4x2_t q4 = vzipq_f32 (q0, q1);

 3.vuzpq_f32

float32x4x2_t ret = vuzpq_f32 (q0, q1);

 可见,打包 (zip)、拆包(unzip)并不是想当然的可逆的运算

4.vcombine_f32 

float32x2_t a = vget_low_f32(q0);
float32x2_t b = vget_high_f32(q0);float32x4_t ret = vcombine_f32 (a, b);

5. vget_low_f32

float32x2_t low = vget_low_f32(q0); // 取低2位

 

6. vget_high_f32

float32x2_t high = vget_high_f32(q0); // 取高2位

 

7. vtrnq_f32

float32x4x2_t ret = vtrnq_f32 (q0, q1)

 

8. vextq_f32

 
  1. // 拼接两个寄存器并返回从第 n 位开始的大小为4的寄存器 0<=n<=3

  2. res = vextq_f32(q0, q1, 2); //取 q1 低2位,拼接到 q0 的高位,保留 q0 的高2位(移到低位)

  3. // q0, q1 实际数据没有变化

  •  vext_u8 的例子:
uint8x8_t ret = vext_u8 (p, q, 2); // 取 q 的低两位作为 p 的高位,p 向左移动两位腾出空间

9.vget_lane_f32

float lane0 = vget_lane_f32(ss0, 0);// get 0th parameter in vector

 

10. vsetq_lane_f32

float32x4_t res = vsetq_lane_f32(d1[0], q1, 1);//用 d1[0] 的数据替换掉 q1[1](q1 实际数据没有变化)

11.vtbl1_s8

int8x8_t r = vtbl1_s8 (p, q);

12.vrev16_s8

int8x8_t s = vrev16_s8 (q);

 

 三、基本数据类型的转换

1.vcvtq_u32_f32

uint32x4_t ui0 = vcvtq_u32_f32 (q0);

2.vcvtq_s32_f32 

int32x4_t i0 = vcvtq_s32_f32 (q1);

3. vcvtq_f32_s32

float32x4_t f0 = vcvtq_f32_s32 (i0);

 

4.vcvtq_f32_u32

float32x4_t uf0 = vcvtq_f32_u32 (ui0)

四、基本比较运算

1.vceq_f32  

uint32x2_t c = vceq_f32 (a, b); // 等于

2.vceqq_f32

uint32x4_t q = vceqq_f32 (q1, q2); // 等于

 

3. vmaxq_f32

float32x4_t ret = vmaxq_f32 (q2, q1);

4. vminq_f32

float32x4_t ret0 = vminq_f32 (q2, q1);

 

5.vpmax_s8

int8x8_t r = vpmax_s8 (p, q);

 

6.vpmin_s8

int8x8_t s = vpmin_s8 (p, q);

 

五、基本的位运算

 1.vclsq_s32

int32x4_t q1 = vclsq_s32 (q0); // 统计和符号位相同的 bit 数(不包括符号位)

 2.vclzq_s32

int32x4_t q2 = vclzq_s32 (q0); // 统计前缀 0 的个数

 

3.vcnt_s8

 
  1. int8_t d0[8] = {0, 1, 2, 3, 4, 5, 6, 7};

  2. int8x8_t q = vld1_s8(d0);

  3. int8x8_t p = vcnt_s8 (q); // 二进制形式的 1 的个数

 

4.vmvn_s8 

int8x8_t q = vmvn_s8 (p); // 按位取反

  

5.vqneg_s8 

int8x8_t r = vqneg_s8 (p);

 

6. vqshl_s8

 
  1. int8_t d0[8] = {0, 1, 2, 3, 4, 5, 6, 7};

  2. int8_t d1[8] = {1, 1, 2, 2, 3, 3, 4, 4};

  3. int8x8_t p = vld1_s8(d0);

  4. int8x8_t q = vld1_s8(d1);

  5. int8x8_t pq = vqshl_s8 (p, q); // 左移对应的位数

如果移位是负数 ,则变成截断的右移

 
  1. int8_t d0[8] = {0, 1, 2, 3, 4, 5, 6, 7};

  2. int8_t d1[8] = {-1, -1, -2, -2, -3, -3, -4, -4};

  3. int8x8_t p = vld1_s8(d0);

  4. int8x8_t q = vld1_s8(d1);

  5. int8x8_t pq = vqshl_s8 (p, q);

 

六、基本的逻辑运算

 略

 七、基本的算术运算

1.vadd_f32

float32x2_t ss0 = vadd_f32(vget_low_f32(q2), vget_high_f32(q2));//对应元素相加

 

2.vaddq_f32

float32x4_t q4 = vaddq_f32 (q1, q2);

 

3.vpadd_f32

float32x2_t ss1 = vpadd_f32(vget_low_f32(q2), vget_high_f32(q2));//相邻元素相加

3.vmulq_f32

float32x4_t res0 = vmulq_f32(q0, q1); //点乘

 

4. vmlaq_f32

float32x4_t res1 = vmlaq_f32(q0, q1, q2);// q0 + q1*q2

 

 

5.vmlaq_lane_f32

 
  1. //  ri = ai + bi * c[d];

  2. float32x4_t res = vmlaq_lane_f32(q0, q1, vget_low_f32(q2), 0);//取 q2 的第0个数,分别与 q1 中的 4 个数相乘,得到 4 个结果与 q0 累加

 

6.vmaxq_f3

float32x4_t max = vmaxq_f32(q1, q2);//对应元素比较,取最大

 

 7.vrecpeq_f32

float32x4_t q5 = vrecpeq_f32 (q1); // 倒数

 8.vrsqrteq_f32

float32x4_t q6 = vrsqrteq_f32 (q1); // 倒数平方根

待续


http://www.ppmy.cn/news/520357.html

相关文章

【电赛仪器仪表】基于MATLAB的数字滤波器设计与ARM官方DSP库的结合

主要内容 Ⅰ. 数字滤波器基础知识1.数字滤波器的概念2.数字滤波器的分类3.数字滤波器的技术指标 Ⅱ.使用MATLAB软件设计两类数字滤波器1.FIR滤波器1)窗函数简介2)filterDesigner使用 2.IIR滤波器 Ⅲ.数字滤波器与官方DSP库结合使用1.DSP库的安装使用2.DSP库滤波器函数介绍1)FIR…

TMS320F28335调用官方库进行FFT频谱分析

移植 首先进入TI官网下载软件支持包&#xff0c;我们需要的FFT官方包就在这里边。 TMS320F28335 data sheet, product information and support | TI.com 下载完成后&#xff0c;解压。进入以下目录 C2000Ware_4_01_00_00_Software__all\C2000Ware_4_01_00_00\libraries\dsp…

【STM32】STM32F4调用DSP库实现FFT运算

写在前面 最近在整理之前的stm32笔记&#xff0c;打算把一些有价值的笔记发到CSDN分享一下。 奎斯特定理 在进行模拟/数字信号的转换过程中&#xff0c;当采样频率F大于信号中最高频率 fmax 的 2 倍时(F>2*fmax)&#xff0c;采样之后的数字信号完整地保留了原始信号中的信…

【STM32】 DSP库函数的一些基本使用

对于一些刚接触STM32的童靴来说&#xff0c;DSP库一定是一个陌生的东西。通俗来说&#xff0c;DSP库就是为了让MCU能够使用像DSP&#xff08;数字信号处理的芯片&#xff09;功能弄的一些官方库函数&#xff0c;它是基于MCU的FPU&#xff08;浮点运算功能&#xff09;的&#x…

STM32_arm_sin_f32和sin的区别

FOC控制中会用到三角函数 调试通信的时候&#xff0c;也会用三角函数产生一个测试波形 优化三角函数的运行时间是一个不可避免的事情&#xff0c;而幸运的是&#xff0c;前人已经把树种上了。 用专用的浮点运算单元FPU来做浮点运算&#xff0c;比用STM32本身来做浮点运算要快…

STM32F1 FFT初试

1、STM32有dsp库&#xff0c;百度一堆的文章&#xff0c;注意有f4有硬件fft可以使用arm_rfft_fast_init_f32&#xff0c;F1不能使用&#xff0c;F1可以使用arm_cfft_radix4_init_f32&#xff0c;256长度1024长度&#xff0c;arm_cfft_radix2_init_f32 512长度。 2、采样率FFT_S…

UVM1.2究竟在UVM1.1上做了哪些升级

想必大家平时也没有很注意UVM1.1版本和UVM1.2版本的不同之处&#xff0c;只有在用一些以前UVM1.1能支持的功能&#xff0c;到了UVM1.2却出现编译报错&#xff0c;找不到对应的变量或者函数或者类的时候&#xff0c;才意识到这两个版本的差异。笔者也是遇到了1个打印问题&#x…

【webFlux】使用zip()或concatMap操作符处理两个表,基于条件修改两个表

要响应式地处理两个列表,并基于条件修改第一个列表的一个bean,并根据条件修改第二个列表中对应bean的属性,你可以使用RxJava的操作符来实现。 以下是一个示例代码,展示了如何响应式地处理两个列表并进行相应的修改操作: Observable<List<Bean1>> list1Obser…