一:简介
ARM NEON 是ARM Cortex-A和Cortex-R系列处理器的一种SIMD指令集的扩展结构。其中SIMD表示单指令多数据指令,与之对应的是SISD,单指令单数据。早期的ARM指令集为通用计算型指令集,指令集都是针对单个数据进行计算,没有并行计算的功能。随着版本的更新,后面逐渐加入了一些复杂的指令以及并行计算的指令。而NEON指令是专门针对大规模的并行运算而设计的。 neon指令集的几个特点:寄存器被同一数据类型的元素的向量,例如float32x4_t 表示4个float数据构成的向量,可以放到一个四字的Q寄存器中。数据类型支持8/16/32/64bit的整数和单双精度浮点数。指令在所有通道中执行相同的操作,例如vmulq_f32(v_a, v_b) 表示将a向量和b向量中对应通道元素相乘。
Neon使用方法:
2. Neon instrinsics(c函数)
3. Neon assembly
xj3浮点转定点项目runtime实现中使用了Neon技术,主要用于相关cpu op的优化,对于使用custom op功能的客户,也可以用neon指令加速custom op的速度。
二:Neon Instrinsics
Neon intrinsics 函数为Neon操作提供C函数调用接口,编译器会将这些函数调用编译成相关的NEON指令。
几个常用函数介绍:
vdupq_n_type:用类型为type的数值,初始化一个元素类型为type的新vector的所有元素, 例如 float32x4_t v = vdupq_n_f32(3.5)
vldnq_type: 按交叉顺序将内存的数据装入neon的寄存器,并返回元素类型为type 纬度为n * (128/sizeof(type))的vector,例如:float32x4x4_t v = vld4q_f32(input), 表示从input指示的内存开始交叉加载16个数据,每四个一组构成二维数组的一行,最终返回4x4的一个vector,例如RGB分解,用vld3q_u8指令可以快速完成r, g, b的提取。
vstnq_type: 将元素类型为type 维度为n*(128/sizeof(type))的vector的所有元素装入内存。
vaddq_type:两个元素类型为type的vector对应通道元素相加,返回相加后的vector
vsubq_type:两个元素类型为type的vector对应通道元素相减,返回相加后的vector
vmulq_type: 两个元素类型为type的vector对应通道元素相乘,返回相加后的vector
vmlaq_type(a, b, c): 乘加操作 a+b*c
.........
三:示例
以两个简单示例介绍neon的使用
1. sigmoid(在xj3开发版上实测,速度可以优化4倍多)
2. 矩阵转置(以4x4矩阵为例,大矩阵可以切成4x4的矩阵块,再分别转置)
四:优化原则
先是c代码算法层面的优化,然后是intrinsics优化,最后是汇编优化。
intrinsics与assembly方式对比

五:参考资料
