专栏算法工具链Neon初识

Neon初识

fdy2020-12-23
496
0

一:简介

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使用方法:

1. 使用已经包含了NEON的开源库,如https://github.com/ARM-software/ComputeLibrary

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 instrincs提供的函数有很多,具体可以参考 IHI0073D_arm_neon_intrinsics_ref.pdf(intrinsics指令表)

三:示例

以两个简单示例介绍neon的使用

1. sigmoid(在xj3开发版上实测,速度可以优化4倍多)

2. 矩阵转置(以4x4矩阵为例,大矩阵可以切成4x4的矩阵块,再分别转置)

四:优化原则

先是c代码算法层面的优化,然后是intrinsics优化,最后是汇编优化。

intrinsics与assembly方式对比

五:参考资料

IHI0073D_arm_neon_intrinsics_ref.pdf(intrinsics指令表)
https://github.com/Tencent/ncnn (有丰富的优化事例,对aarch64与aarch32分别优化)
算法工具链
杂谈
评论0
0/1000