NEON介绍

在移动平台上进行一些复杂算法的开发,一般需要用到指令集来进行加速。NEON 技术是 ARM Cortex™-A 系列处理器的 128 位 SIMD(单指令,多数据)架构扩展,专门针对大规模并行运算设计的,旨在为消费性多媒体应用程序提供灵活、强大的加速功能,从而显著改善用户体验。

其本质上使用的是128位NEON SIMD寄存器,这意味着如果操作32位浮点数,可同时操作4个(变量可定义:float32x4_t);如果操作 16 位整数(short),可同时操作 8 个(变量可定义:int16x8_t);而如果操作 8 位整数,则可同时操作 16 个(变量可定义:int8x16_t)。

ARMv7 NEON 指令集架构具有 16 个 128 位的向量寄存器,命名为 q0~q15。这 16 个寄存器又可以拆分成 32 个 64 位寄存器,命名为 d0~d31。其中qn和d2n,d2n+1是一样的,故使用汇编编写代码时要注意避免产生寄存器覆盖。如下图所示:

NEON数据类型

NEON的数据类型如下图:

neon的数据类型float32x4_t 可以理解为vector< float32 > (4),同理typexN_t即为vector< type>(N)。在NEON编程中,对单个数据的操作可以扩展为对寄存器,也即同一类型元素矢量的操作,因此大大减少了操作次数。

NEON中指令分为正常指令、宽指令、窄指令、饱和指令、长指令这几类:

正常指令:数据宽度不变

//操作数为int16x4_t,结果数为int16x4_t

int16x4_t vadd_s16 (int16x4_t __a, int16x4_t __b);

长指令:源操作数宽度相同 结果宽度扩展 L标记

//操作数为int16x4_t,结果数为int32x4_t,vaddl_s16中l标志指令为长指令

int32x4_t vaddl_s16 (int16x4_t __a, int16x4_t __b);

宽指令:源操作数宽度不同 结果宽度对齐 W标记

//操作数一个为uint32x4_t,一个为uint16x4_t,结果对齐uint32x4_t,w标志指令为宽指令

uint32x4_t vaddw_u16 (uint32x4_t __a, uint16x4_t __b);

窄指令:源操作数宽度相同 结果宽度变窄 N标记

//操作数为uint32x4_t,结果数为uint16x4_t,n标志指令为窄指令

uint16x4_t vaddhn_u32 (uint32x4_t __a, uint32x4_t __b);

饱和指令:结果溢出就是饱和指令 Q标记

NEON官方示例及详解

通过一个示例来解释如何利用NEON内置函数来加速实现统计一个数组内的元素之和。

#include

using namespace std;

float sum_array(float *arr, int len)

{

if(NULL == arr || len < 1)

{

cout<

return 0;

}

float sum(0.0);

for(int i=0; i

{

sum += *arr++;

}

return sum;

}

对于长度为N的数组,上述算法的时间复杂度为O(N)。

采用NEON函数进行加速:

#include

#include//需包含的头文件

using namespace std;

float sum_array(float *arr, int len)

{

if(NULL == arr || len < 1)

{

cout<

return 0;

}

int dim4 = len >> 2; // 数组长度除4整数

int left4 = len & 3; // 数组长度除4余数

float32x4_t sum_vec = vdupq_n_f32(0.0);//定义用于暂存累加结果的寄存器且初始化为0

for (; dim4>0; dim4--, arr+=4) //每次同时访问4个数组元素

{

float32x4_t data_vec = vld1q_f32(arr); //依次取4个元素存入寄存器vec

sum_vec = vaddq_f32(sum_vec, data_vec);//ri = ai + bi 计算两组寄存器对应元素之和并存放到相应结果

}

//将累加结果寄存器中的所有元素相加得到最终累加值

float sum = vgetq_lane_f32(sum_vec, 0)+vgetq_lane_f32(sum_vec, 1)+vgetq_lane_f32(sum_vec, 2)+vgetq_lane_f32(sum_vec, 3);

for (; left4>0; left4--, arr++)

sum += (*arr) ; //对于剩下的少于4的数字,依次计算累加即可

return sum;

}

上述算法的时间复杂度为O(N/4),原因在于我们每次往寄存器加载4个float值,然后同时相加。相当于原来需要N次加法操作而现在只需要N/4即可。如果使用更多的寄存器,则可以完成更高倍数的加速。

上述用到的几个NEON指令解释为:

float32x4_t vdupq_n_f32(float32_t val):将val复制四份放入返回的寄存器中。

float32x4_t vld1q_f32(float32_t const * ptr):从地址ptr依次向后加载四个元素放入返回的寄存器中。

float32x4_t vaddq_f32(float32x4_t a, float32x4_t b):返回a+b的值,向量运算,四个值同时相加。

float32_t vgetq_lane_f32(float32x4_t v, const int lane):返回v中某一个lane的值

除以上的操作外,NEON还支持很多的操作,如矢量相减、矢量相乘、矢量乘加、矢量类型转换等等。

NEON手册

以下链接为NEON内置函数的手册,当需要用到某些NEON操作时,可以通过手册查看使用方法。

NEON内置函数详细手册

arm 饱和指令_ARM平台下NEON使用方法详解相关推荐

  1. ElasticSearch-.net平台下c#操作ElasticSearch详解

    ElasticSearch系列学习 ElasticSearch第一步-环境配置 ElasticSearch第二步-CRUD之Sense ElasticSearch第三步-中文分词 ElasticSea ...

  2. arm 饱和指令_ARM aarch64汇编学习笔记(九):使用Neon指令(一)

    NEON是一种基于SIMD思想的ARM技术. SIMD, Single Instruction Multiple Data,是一种单条指令处理多个数据的并行处理技术,相比于一条指令处理一个数据,运算速 ...

  3. arm 饱和指令_ARM内核全解析,从ARM7,ARM9到CortexA7,A8,A9,A12,A15到CortexA53,A57

    小伙伴们,你们的干货又来啦~快来拿好你的小板凳学习吧~ 首先我们介绍下 ARM cortex三个A,R ,M系列产品图谱及对应应用领域 1,A系列:顶级主控,手机平板AP应用处理器,GPS... 2, ...

  4. 【转】angularjs指令中的compile与link函数详解

    这篇文章主要介绍了angularjs指令中的compile与link函数详解,本文同时诉大家complie,pre-link,post-link的用法与区别等内容,需要的朋友可以参考下 通常大家在使用 ...

  5. FANUC机器人动作指令的定位类型FINE和CNT详解

    FANUC机器人动作指令的定位类型FINE和CNT详解 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到网站. FANUC机器人的定位类型,即定义动作指令中 ...

  6. 方舟服务器怎么请求芯片,方舟指令哔哩芯片这么获得?哔哩芯片获得方法详解分享...

    方舟指令哔哩芯片这么获得?哔哩芯片是目前游戏在10月25日更新后上线的道具,小伙伴们可能通过参加比赛获取哦!下面是小编分享的获取途径详解,感兴趣的可以一起来关注下哦! 哔哩芯片怎么获得? 活动时间: ...

  7. 我的世界java版区块显示_我的世界手游区块显示指令分享:区块玩法操作详解[多图]...

    我的世界手游区块是一个独特的机制,很多玩家对于区块是什么不太了解,区块显示指令以及区块的产生不是很熟悉,为了帮助到大家,今天小编就为大家带来我的世界手游区块显示指令分享:区块玩法操作详解的内容,希望大 ...

  8. 【genius_platform软件平台开发】第四点:ARM NEON Intrinsics 使用详解

    目录 前言 SIMD简介 ARM NEON Intrinsics简介 函数改写示例 结语 前言 最近公司在视频直播项目中要使用H.265/HEVC,具体的是使用HW硬件编码H.264/AVC,云端转码 ...

  9. arm汇编指令_ARM汇编伪指令介绍.

    符号定义( Symbol Definition )伪指令 符号定义伪指令用于定义 ARM 汇编程序中的变量.对变量赋值以及定义寄存器的别名等操作. 常见的符号定义伪指令有如下几种: - 用于定义全局变 ...

最新文章

  1. 腾讯Bugly异常崩溃SDK接入
  2. python输入语句-Python中的模块导入和读取键盘输入的方法
  3. 小赋诗歌一首,以感学生时代结束
  4. 用过的jQuery记录
  5. Linux系统编程19:基础IO之了解Linux中的标准输入和输出以及相关的系统调用接口(如write,read等)
  6. Linux 音频驱动
  7. Python Day47索引
  8. 金笛JDMail邮件系统从源头上为企业铸造防lj邮件墙--4
  9. android_dialog_2
  10. 【技术文档】jeecg3.7.3-maven搭建环境入门
  11. Batch Normalization 算法解析
  12. jquery radio设置选中_前端jQuery实战之 attr() 和 prop() 的区别
  13. 美团外卖订单系统演进
  14. 北大青鸟(邯郸翱翔)网络校区
  15. 熊猫压缩怎么使用_记录随时间变化的PagerDuty事件(使用熊猫)
  16. intel(r)wireless-ac9462异常//笔记本电脑网络无法连接???吐血后总结 :一次解决,史上最全,N种方案
  17. libusb 串口 android,libusb开发通讯问题
  18. 方舟编译器的构建(笔记)
  19. 农民伯伯android,[同人]墨水儿哥哥乡下小山村的农民伯伯生活.avi
  20. 中国人民大学于坤教授:以社会支持体系提升就业力 | 牛客大咖说

热门文章

  1. rabbitmq的整体架构一览
  2. 开源中国源码学习笔记
  3. Q+会带来什么样的互联网时代?
  4. ETC核心技术团队CTO空降上海,引领高校区块链技术风潮
  5. java集合框架综述
  6. Lua代码加密,防止代码反编译
  7. Logon database Tiger引起DataGuard不同步问题
  8. Gartner:中国CIO们正将IT预算投向数字化
  9. sicp 4.2.1两题
  10. Elmah 日志记录组件