NEON
ARM NEON (Advanced SIMD, Single Instruction, Multiple Data) 是 ARM 处理器架构中的一个扩展,用于加速多媒体和信号处理应用。NEON 支持一组向量操作指令,通常通过内建函数(intrinsics)来实现,可以同时处理多个数据元素,提高数据并行处理能力,可以直接在 C/C++ 代码中使用这些指令 参考资料:1
__ARM_NEON 是一个预处理宏,表示 ARM 的 NEON SIMD(Single Instruction, Multiple Data)扩展是否可用。NEON 是 ARM 架构的一部分,提供了高级 SIMD 加速功能,适用于多媒体处理、信号处理、图像处理等领域。
当编写需要利用 ARM NEON 指令集的代码时,可以使用 __ARM_NEON 来检查编译器是否支持 NEON,并根据这个条件编译相应的代码。
使用 __ARM_NEON 的示例
以下是如何使用 __ARM_NEON 宏来检查 NEON 支持并编写不同代码的示例:
#include <iostream>
#ifdef __ARM_NEON
#include <arm_neon.h>
#endif
void process_with_neon() {
#ifdef __ARM_NEON
std::cout << "NEON is supported. Running NEON optimized code." << std::endl;
// 使用 NEON 进行加速的代码
float32x4_t a = vdupq_n_f32(1.0f);
float32x4_t b = vdupq_n_f32(2.0f);
float32x4_t c = vaddq_f32(a, b);
float result[4];
vst1q_f32(result, c);
std::cout << "Result: " << result[0] << ", " << result[1] << ", " << result[2] << ", " << result[3] << std::endl;
#else
std::cout << "NEON is not supported. Running fallback code." << std::endl;
// 使用非 NEON 代码
float a = 1.0f;
float b = 2.0f;
float c = a + b;
std::cout << "Result: " << c << std::endl;
#endif
}
int main() {
process_with_neon();
return 0;
}加载和存储指令
vld1q_f32(ptr): 加载128位浮点矢量(4个32位浮点数)。vst1q_f32(ptr, val): 存储128位浮点矢量(4个32位浮点数)。vdupq_n_s32:创建包含 4 个相同 32 位整数的向量
float32x4_t vec = vld1q_f32(data); // 从data指针加载128位浮点矢量 vst1q_f32(output, vec); // 将128位浮点矢量存储到output指针
算术指令
vaddq_f32(a, b): 4x32位浮点矢量加法。vsubq_f32(a, b): 4x32位浮点矢量减法。vmulq_f32(a, b): 4x32位浮点矢量乘法。vmlaq_f32(a, b, c): 4x32位浮点矢量乘加。vaddq_s32(a, b):4x32位有符号整数矢量加法
float32x4_t result = vaddq_f32(a, b); // 矢量加法
result = vsubq_f32(a, b); // 矢量减法
result = vmulq_f32(a, b); // 矢量乘法
result = vmlaq_f32(a, b, c); // 矢量乘加
逻辑指令
vandq_u32(a, b): 128位无符号整型矢量按位与。vorrq_u32(a, b): 128位无符号整型矢量按位或。veorq_u32(a, b): 128位无符号整型矢量按位异或。
uint32x4_t result = vandq_u32(a, b); // 按位与
result = vorrq_u32(a, b); // 按位或
result = veorq_u32(a, b); // 按位异或
比较指令
vcgtq_f32(a, b): 比较128位浮点矢量大于。vcgeq_f32(a, b): 比较128位浮点矢量大于等于。vcltq_f32(a, b): 比较128位浮点矢量小于。vcleq_f32(a, b): 比较128位浮点矢量小于等于。
uint32x4_t result = vcgtq_f32(a, b); // 比较大于
result = vcgeq_f32(a, b); // 比较大于等于
result = vcltq_f32(a, b); // 比较小于
result = vcleq_f32(a, b); // 比较小于等于
移位指令
vshlq_n_u32(a, n): 左移128位无符号整型矢量中的每个元素。vqshrn_n_s32(a, n): 对 32 位有符号整数向量进行右移位缩窄操作,并进行饱和处理
uint32x4_t result = vshlq_n_u32(a, 1); // 左移1位
result = vshrq_n_u32(a, 1); // 右移1位
数据类型
NEON 支持多种数据类型,常见的数据类型有:
int8x8_t,int8x16_t,uint8x8_t,uint8x16_t:8位整型。int16x4_t,int16x8_t,uint16x4_t,uint16x8_t:16位整型。int32x2_t,int32x4_t,uint32x2_t,uint32x4_t:32位整型。int64x1_t,int64x2_t,uint64x1_t,uint64x2_t:64位整型。float32x2_t,float32x4_t:32位浮点数。float64x1_t,float64x2_t:64位浮点数。