ARM NEON优化笔记
条评论对于ARM来说,也提供了类似Intel AVX向量指令集的NEON向量指令集,提供了灵活的向量化编程。对于ARM v7架构以上的产品,NEON提供了丰富的向量化指令,能够带来很好的性能提升。像未来手持设备添加机器学习或者其他耗时严重的代码,利用NEON绝对是很好的选择。而且目前Nvidia的tk1开发板使用的是一颗A15的ARM,充分优化也可以带来很好的性能。
NEON支持64位和128位的向量寄存器,因此其向量宽度有64位和128位可选。使用NEON指令时不需要数据对齐,GCC支持NEON指令集的c语言接口,声明在arm_neon.h文件中。
数据结构
NEON指令集支持的数据结构的命名格式分成3个部分,分割方式是”_“和”x”,形式就是Type_SizexNum_t
,例如float32x4_t, uint16x8_t等,其具体的含义如下:
- Type 第一部分表示数据类型,目前只支持float,int和uint。
- Size 第二部分表示每个元素的数据长度位数,float只支持32位,int和uint支持8位,16位,32位和64位。
- Num 第三部分表示元素的数量,即含有多少个Size大小的数量,由于NEON只支持64位和128位的向量寄存器,因此Size乘以Num必须等于64或128
指令结构
NEON向量化指令函数的操作非常灵活,允许参数和返回值的位宽不同的操作,即支持操作几个128位宽的向量返回一个64位宽的向量,或者操作几个64位宽的向量返回一个128位宽的向量,当然参数返回值位宽相同更是不成问题;他还支持标量变量的参与,能够在参数中设定使用标量变量。
由于指令种类较多,我们把指令结构分成两种,一种是含标量操作指令,另一种是纯向量的操作指令(即不含标量操作),下面分别描述其命名方式。
对于 含标量操作 的函数,函数名称分为4个部分,其形式为v op dt_n/lane_type
,例如vld1q_lane_u64, vst1q_lane_s16等。对于 纯向量操作 的函数,函数名称分为3个部分,形式为v op dt_type
,例如vadd_u64,vmlaq_f32,vmla_u32等,具体含义如下:
- op表示使用的是什么操作,如add,mla等等。
- dt是返回值和参数长度表示符。
1). 如果返回值和参数长度都是64位,dt为空;
2). 如果返回值和参数长度都是128位,dt为q;
3). 如果返回值为比参数长,且参数长度为64位,返回值为128位,dt为l(英文字母l);
4). 如果多个参数长度不一致且都不大于返回值长度(一个参数长度为64位,另一个为128位,返回值长度为128位),dt为w;
5). 如果返回值长度比参数长度小,dt为n。 - 含标量操作的函数名称中才有这一部分,n/lane表示标量的来源。如果参数中的标量就是一个标量,这个地方使用n; 如果参数中的标量是一个向量中的一个元素,这个地方使用lane。
- type表示元数据类型缩写。u8表示uint8; u16表示uint16; u32表示uint32; s8表示int8; s16表示int16; s32表示int32; f32表示float32。
看完这些,对照ARM提供的NEON手册再好好看看,很快就能理解了。这里给个官方手册地址( http://infocenter.arm.com/help/topic/com.arm.doc.dui0491h/Badcdfad.html )。这里也举几个例子来说明一下。
int8x8_t vadd_s8(int8x8_t a, int8x8_t b); // VADD.I8 d0,d0,d0
没有n/lane部分,是纯向量操作,做的加法操作,参数和返回值位宽相同,都是int8x8的64位向量,类型是int8。
float32x4_t vmulq_f32(float32x4_t a, float32x4_t b); // VMUL.F32 q0,q0,q0
没有n/lane部分,是纯向量操作,做的是乘法操作,参数和返回值位宽相同,都是float32x4的128位向量,类型是float32。
uint32x4_t vld1q_lane_u32(__transfersize(1) uint32_t const * ptr, uint32x4_t vec, __constrange(0,3) int lane); // VLD1.32 {d0[0]}, [r0]
带有lane说明含有标量,做的是load操作,返回值和参数位宽相同,都是uint32x4的128位向量,类型是uint32。
int16x8_t vmull_s8(int8x8_t a, int8x8_t b); // VMULL.S8 q0,d0,d0
没有n/lane部分,是纯向量操作,做的是乘法操作,返回值是的int16x8的128位向量,而参数是int8x8的64位向量,操作的类型是int8。
这里的东西主要是为了解释NEON指令集函数的命名方式,但他也有一些特殊的函数,例如没有返回值的函数,或者参数数量多于2个的函数等,对于这些特例,上面的规则只是一个参考性方式。详细内容还是要参见NEON的官方手册啊。
本文标题:ARM NEON优化笔记
文章作者:throneclay
发布时间:2015-12-30
最后更新:2022-08-03
原始链接:http://blog.throneclay.top/2015/12/30/armneon/
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 CN 许可协议。转载请注明出处!