性能优化(CPU优化技术)ARM Neon 详解

原文来自ARM neon详解

🎬个人简介:一个全栈工程师的升级之路!
📋个人专栏:高性能(HPC)开发基础教程
🎀CSDN主页 发狂的小花
🌄人生秘诀:学习的本质就是极致重复!

目录

NEON 学习参考文档:

三大主流芯片架构

ARM 2、MIPS 3、x86

1、neon简述

2、Arm 高级SIMD发展历史

3、 为什么要用NEON

4、NEON指令格式

5、 NEON编程基础

6、neon 实际应用参考


NEON 学习参考文档:

ARM NEON优化(一)——NEON简介及基本架构 - Orchid Blog

http://zyddora.github.io/2016/02/28/neon_1/

neon intrinsics函数

Intrinsics – Arm Developer

https://developer.arm.com/architectures/instruction-sets/intrinsics/

三大主流芯片架构

ARM 2、MIPS 3、x86

编译器自动向量化,往往发挥不了neon的最佳性能,这时候可能需要你借组内联的Neon Intrinsics(arm_neon.h提供),甚至嵌套neon的汇编指令来进行优化

1、neon简述

NEON是指适用于Arm Cortex-A系列处理器的一种高级SIMD(单指令多数据)扩展指令集。NEON 技术可加速多媒体和信号处理算法(如视频编码/解码、2D/3D 图形、游戏、音频和语音处理、图像处理技术、电话和声音合成)。Single Instruction Multiple Data (SIMD)顾名思义就是“一条指令处理多个数据(一般是以2为底的指数数量)”的并行处理技术

NEON 指令可执行并行数据处理:

个人理解 neon就是通过对arm内部的一些特有寄存器做运算操作,以便能加速运算

2、Arm 高级SIMD发展历史

3、 为什么要用NEON

(1)支持整数和浮点操作,以确保适合从编解码器、高性能计算到 3D 图形等广泛应用领域。

(2)与 Arm处理器紧密结合,提供指令流和内存的统一视图,编程比外部硬件加速器更简单。

4、NEON指令格式

NEON寄存器:

16×128-bit寄存器(Q0-Q15);
或32×64-bit寄存器(D0-D31)
或上述寄存器的组合。
ps每一个Q0-Q15寄存器映射到一对D寄存器


 

Q寄存器是虚的实际不在存在

数据处理指令类别:

(1)Long instructions

操作双字vectors,生成四倍长字vectors 结果的宽度一般比操作数加倍,同类型 在指令中加L

(2) Wide instructions

操作双字 + 四倍长字,生成四倍长字 结果和第一个操作数都是第二个操作数的两倍宽度 在指令中加W

(3)Narrow instructions

操作四倍长字,生成双字 结果宽度一般是操作数的一半 在指令中加N

数据类型表示:

(u)int8x8_t;

(u)int8x16_t;

(u)int16x4_t;

(u)int16x8_t;

(u)int32x2_t;

(u)int32x4_t;

(u)int64x1_t;

其中,第一个数字代表的是数据类型宽度为8/16/32/64位,第二个数字代表的是一个寄存器中该类型数据的数量。如int16x8_t代表16位有符号数,寄存器中共有8个数据 ,

为什么 数据类型为64 ,因为本来 寄存器大小 16个 128bit 寄存器, 映射处理后变为 32 * 64bit

参考示例

int16x8_t vqaddq_s16 (int16x8_t, int16x8_t)

int16x4_t vqadd_s16 (int16x4_t, int16x4_t)

第一个字母'v'指明是vector向量指令,也就是NEON指令;

第二个字母'q'指明是饱和指令,即后续的加法结果会自动饱和;

第三个字段'add'指明是加法指令;

第四个字段'q'指明操作寄存器宽度,为'q'时操作QWORD, 为128位;未指明时操作寄存器为DWORD,为64位;

第五个字段's16'指明操作的基本单元为有符号16位整数,其最大表示范围为-32768 ~ 32767;

形参和返回值类型约定与C语言一致。

其它可能用到的助记符包括:

l 长指令,数据扩展

w 宽指令,数据对齐

n 窄指令, 数据压缩

指令格式

V{<mod>}<op>{<shape>}{<cond>}{.<dt>}{<dest>}, src1, src2

<mod>

<op> 表示 操作运算符 如ADD, SUB, MUL

<shape> - Shape,即前文中的Long (L), Wide (W), Narrow (N).

<.dt> - Data type, such as s8, u8, f32 etc.

<dest> - Destination.

<src1> - Source operand 1.

<src2> - Source operand 2.

注: {} 表示可选的参数。

VADD.I16 D0, D1, D2 @ 16位加法 VMLAL.S16 Q2, D8, D9 @ 有符号16位乘加

5、 NEON编程基础

现在我们可以开始使用NEON开始加速我们的应用了。使用NEON 技术通常有下列四种方式:

调用NEON优化过的库函数
使用编译器自动矢量化选项
使用NEON intrinsics指令
手写NEON汇编
(1)调用库函数

用户只需要在程序中直接调用NEON优化过的库函数就可以了,简单易用。目前你有下列库可以选择:

Arm Compute library

一系列经过Arm CPU和GPU优化过的底层函数库。用于图像处理、机器学习和计算机视觉。更多信息: https://developer.Arm.com/technologies/compute-library

Ne10开源库

由Arm主导开发的,目前提供了比较通用的数学函数,部分图像处理函数,以及FFT函数。
Project Ne10: An Open Optimized Software Library Project for the Arm Architecture @ GitHub
http://projectne10.github.io/Ne10/

PS arm 平台 系列处理器说明 其中 ARM CORTEX-A系列对应 ARMV7 参考如下

ARM平台处理器简介-ARMv7_WangMark的专栏-CSDN博客_armv7
https://blog.csdn.net/petib_wangwei/article/details/40187207

(2)使用编译器自动矢量化选项

如 gcc 编译加上 参数 -mfpu=neon -mcpu

(3)使用NEON intrinsics指令

         见下面实际应用参考中描述

(4) 手写NEON汇编

实际除非对汇编很了解,否则一般开发比较少用,实际intrinsics函数底层也是调用neon汇编的

6、neon 实际应用参考

(1)C语言__attribute__的使用

__attribute__ 语法格式为:__attribute__ ((attribute-list))

attribute-list 参数为可以设置函数属性(Function Attribute )、变量属性(Variable Attribute )和类型属性(Type Attribute )

其位置约束为:放于声明的尾部“ ;” 之前

关键字__attribute__ 也可以对结构体(struct )或共用体(union )进行属性设置。大致有六个参数值可以被设定,即:aligned, packed, transparent_union, unused, deprecated 和 may_alias 。

在使用__attribute__ 参数时,你也可以在参数的前后都加上“__” (两个下划线),例如,使用__aligned__而不是aligned ,这样,你就可以在相应的头文件里使用它而不用关心头文件里是否有重名的宏定义。

如调用neon作用函数 表示以下函数调用 arm_neon.h Intrinsics函数

__attribute__((target("fpu=neon")))

static void neon_accelator_vector_2_bias(short *input, float *output, float *bias)

{

/*

c code logic

for(int i=0;i<2;i++)

{

float temp = (float)(*(input+i));

*(output+i) = temp*(*bias);

}

*/

int16x4_t input_s16vec0 ;

memset(&input_s16vec0, 0, sizeof(input_s16vec0));

vld1_lane_s16(input,input_s16vec0,0);

input++;

vld1_lane_s16(input,input_s16vec0,1);

int32x4_t input_s32vec0 = vmovl_s16(input_s16vec0);

float32x4_t bias_f32vec = vld1q_f32 (bias);

float32x4_t input_f32vec0 = vcvtq_f32_s32(input_s32vec0);

float32x4_t output_f32vec0= vmulq_f32 (input_f32vec0, bias_f32vec);

vst1q_lane_f32(output,output_f32vec0,0);

output++;

vst1q_lane_f32(output,output_f32vec0,1);

}

(2)使用 arm_neon.h Intrinsics函数 需要加入-mfloat-abi=softfp -mfpu=neon指令

(3)指令函数使用

正常指令:生成大小同样且类型通常与操作数向量同样的结果向量;

Vector add(正常指令): vadd -> ri = ai + bi; r, a, b have equal lane sizes--*/

int8x8_t vadd_s8 (int8x8_t __a, int8x8_t __b);//_mm_add_epi8

int16x4_t vadd_s16 (int16x4_t __a, int16x4_t __b);//_mm_add_epi16

int32x2_t vadd_s32 (int32x2_t __a, int32x2_t __b);//_mm_add_epi32

int64x1_t vadd_s64 (int64x1_t __a, int64x1_t __b);//_mm_add_epi64

长指令:对双字向量操作数运行运算,生成四字向量的结果。所生成的元素通常是操作数元素宽度的两倍

Vector long add(长指令): vaddl -> ri = ai + bi; a, b have equal lane sizes,

result is a 128 bit vector of lanes that are twice the width--*/

int16x8_t vaddl_s8 (int8x8_t __a, int8x8_t __b);

int32x4_t vaddl_s16 (int16x4_t __a, int16x4_t __b);

int64x2_t vaddl_s32 (int32x2_t __a, int32x2_t __b);

uint16x8_t vaddl_u8 (uint8x8_t __a, uint8x8_t __b);

uint32x4_t vaddl_u16 (uint16x4_t __a, uint16x4_t __b);

uint64x2_t vaddl_u32 (uint32x2_t __a, uint32x2_t __b);

并属于同一类型。

宽指令:一个双字向量操作数和一个四字向量操作数运行运算,生成四字向量结果。

vaddw -> ri = ai + bi--*/

int16x8_t vaddw_s8 (int16x8_t __a, int8x8_t __b);

int32x4_t vaddw_s16 (int32x4_t __a, int16x4_t __b);

int64x2_t vaddw_s32 (int64x2_t __a, int32x2_t __b);

uint16x8_t vaddw_u8 (uint16x8_t __a, uint8x8_t __b);

uint32x4_t vaddw_u16 (uint32x4_t __a, uint16x4_t __b);

uint64x2_t vaddw_u32 (uint64x2_t __a, uint32x2_t __b);

窄指令:四字向量Vector rounding halving add: vrhadd -> ri = (ai + bi + 1) >> 1;

shifts each result right one bit, Results are rounded(四舍五入)--*/

int8x8_t vrhadd_s8 (int8x8_t __a, int8x8_t __b);

int16x4_t vrhadd_s16 (int16x4_t __a, int16x4_t __b);

int32x2_t vrhadd_s32 (int32x2_t __a, int32x2_t __b);操作数运行运算,并生成双字向量结果,所生成的元素通常是操作数元素宽度的一半。

饱和指令:当超过数据类型指定的范围则自己主动限制在该范围内。*/

vqadd -> ri = sat(ai + bi);

the results are saturated if they overflow--*/

int8x8_t vqadd_s8 (int8x8_t __a, int8x8_t __b);//_mm_adds_epi8

int16x4_t vqadd_s16 (int16x4_t __a, int16x4_t __b);//_mm_adds_epi16

int32x2_t vqadd_s32 (int32x2_t __a, int32x2_t __b);

int64x1_t vqadd_s64 (int64x1_t __a, int64x1_t __b)

vrhadd -> ri = (ai + bi + 1) >> 1;

vmul -> ri = ai * bi

vmla -> ri = ai + bi * ci

vmlsl -> ri = ai - bi * ci
————————————————

🌈我的分享也就到此结束啦🌈
如果我的分享也能对你有帮助,那就太好了!
若有不足,还请大家多多指正,我们一起学习交流!
📢未来的富豪们:点赞👍→收藏⭐→关注🔍,如果能评论下就太惊喜了!
感谢大家的观看和支持!最后,☺祝愿大家每天有钱赚!!!欢迎关注、关注!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/765619.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI新工具(20240322) 免费试用Gemini Pro 1.5;先进的AI软件工程师Devika;人形机器人Apptronik给你打果汁

✨ 1: Gemini Pro 1.5 免费试用Gemini Pro 1.5 Gemini 1.5 Pro是Gemini系列模型的最新版本&#xff0c;是一种计算高效的多模态混合专家&#xff08;MoE&#xff09;模型。它能够从数百万个上下文Token中提取和推理细粒度信息&#xff0c;包括多个长文档和数小时的视频、音频…

ASP.NET控件

目录 TextBox 控件 Button 控件 HyperLink 控件 CheckBox 控件 RadioButton 控件 ListBox 控件 DropDownList 控件 Repeater 控件 DataList 控件 GridView 控件 RequiredFieldValidator 控件 RangeValidator 控件 CompareValidator 控件 RegularExpressionValidat…

C++读取文本文件中的汉字出现乱码的原因及解决措施

大家好&#xff01; 作者今天在写代码时遇到了读取文本文件中的汉字时出现乱码的情况&#xff0c;所以本文介绍Windows操作系统中&#xff0c;C读取文本文件中的汉字出现乱码情况原因及解决措施。 下面代码可以读取Stu.txt中的内容并输出&#xff1a; ifstream ifs; ifs.open(…

拌合楼管理软件开发(十一) 海康威视车牌识别摄像头安装调试,记录犯经验主义错误不断自己打脸过程

前言: 从小白开始 海康威视的摄像头接触过,包括前面也都开发了调用sdk开发拍照和视频预览,以及通过事件警报获取数据的。接触到的像头都是12v或者24v电源&#xff0c;或者是POE供电的&#xff0c;先入为主了觉得都是这样&#xff0c;结果打脸了。 一、设备选型&#xff1a; 最开…

MySQL 经典练习 50 题 (记录)

前言&#xff1a; 记录一下sql学习&#xff0c;仅供参考基本都对了&#xff0c;不排除有些我做的太快做错了。里面sql不存在任何sql优化操作&#xff0c;只以完成最后输出结果为目的&#xff0c;包含我做题过程和思路最后一行才是结果。 1.过程: 1.1.插入数据 /* SQLyog Ul…

【机器学习入门 】人工神经网络(一)

系列文章目录 第1章 专家系统 第2章 决策树 第3章 神经元和感知机 识别手写数字——感知机 第4章 线性回归 第5章 逻辑斯蒂回归和分类 第5章 支持向量机 文章目录 系列文章目录前言一、多层感知机二、反向传播算法三、深度神经网络 前言 人工神经网络( Artifical Neural Netw…

蓝桥杯-02-2023蓝桥杯c/c++省赛B组题目

参考 2023 年第十四届蓝桥杯 C/C B组省赛题解 2023蓝桥杯c/c省赛B组题目(最全版)&#xff1a; A&#xff1a;日期统计 这题方法应该很多&#xff0c;没有和别人讨论想法。我的解法思路是&#xff1a;先 load 函数生成所有这一年的合法日期&#xff0c;然后枚举所有可以从数据…

node和npm yarn包管理工具

node和包管理工具 今日目标&#xff1a; 1.dos常用指令 2.node的模块化 3.npm包管理工具 4.yarn的常用指令 5.node的内置模块 00-回顾 # Promose:作用&#xff1a;解决ajax请求响应顺序不可控的问题特性&#xff1a;1. Promise是一个构造函数&#xff0c;需要通过new关…

uni-app打包证书android

Android平台打包发布apk应用&#xff0c;需要使用数字证书&#xff08;.keystore文件&#xff09;进行签名&#xff0c;用于表明开发者身份。 Android证书的生成是自助和免费的&#xff0c;不需要审批或付费。 可以使用JRE环境中的keytool命令生成。 以下是windows平台生成证…

MySQL、Oracle的时间类型字段自动更新:insert插入、update更新时,自动更新时间戳。设置自增主键id,oracle创建自增id序列和触发器

1. MySQL 支持设置自增id的字段类型&#xff1a;int、bigint、double等数值类型&#xff0c;一般用int、bigint支持设置自动更新时间的字段类型&#xff1a;datetime、timestamp下面sql中的now()函数可以用current_timestamp()替代 1.1. 不指定秒精度 drop table if exists …

Ollama 在本地快速部署大型语言模型,可进行定制并创建属于您自己的模型

# Ollama 在本地快速部署并运行大型语言模型。 macOS 点击下载 Windows 预览版 点击下载 Linux curl -fsSL https://ollama.com/install.sh | sh手动安装指南 Docker 官方的 Ollama Docker 镜像 ollama/ollama 已经在 Docker Hub 上发布。 库 ollama-pythonollama-js…

超详细测试项目——Web电商项目测试点整理.....

虽然说近些年来&#xff0c;软件测试找工作的时候&#xff0c;简历中如果写着电商项目被认为是烂大街的项目&#xff0c;甚至受到根本不了解行情的HR或者部分公司的技术人员的刁难&#xff0c;但是&#xff1a;电商这么流行普遍的项目和应用&#xff0c;这不是很正常么&#xf…

阿里云2核4G云服务器165元一年,ECS u1优惠价格199元一年

阿里云2核4G服务器租用优惠价格&#xff0c;轻量2核4G服务器165元一年、u1服务器2核4G5M带宽199元一年、云服务器e实例30元3个月&#xff0c;活动链接 aliyunfuwuqi.com/go/aliyun 活动链接如下图&#xff1a; 阿里云2核4G服务器优惠价格 轻量应用服务器2核2G4M带宽、60GB高效…

浅谈数据治理之道 数据采集(二)

数据采集是数据治理过程中的一个非常关键和重要地环节&#xff0c;不仅关系到数据的及时性、准确性、完整性和有效性等&#xff0c;还涉及到数据的安全和隐私。其次&#xff0c;涉及到从各种数据源获取原始数据&#xff0c;并将其转换为适合进一步处理和分析的格式。今天 咱们就…

如何从小白,到掌握Python

作为前端开发人员想要掌握Python编程语言&#xff0c;以下是一个学习路径建议&#xff1a; ### 初级阶段&#xff1a; 1. **学习Python基础&#xff1a;** - 学习Python的基本语法、数据类型、流程控制等基础知识。 - 可以通过在线教程、书籍或视频课程来学习&#xff…

Android单片机硬件通信《GPIO通信》

一、什么是GPIO? GPIO&#xff08;英语&#xff1a;General-purpose input/output&#xff09;&#xff0c;通用型输入输出端口&#xff0c;在单片机上一般是通过一个GND引脚和若干个io引脚配合工作。 单片机可以配置GPIO输入输出模式,与外界环境进行通信交互。在输入环境下&…

网络传输(3):TFTP客户端使用

1. 简要说明 在前面的文章中已经讲述了如何安装TFTP客户端和TFTP服务器。其中&#xff1a; tftp-hpa为客户端 tftpd-hpa为服务器。 2. 启动TFTP服务器 我们在设置好相关的TFTP根路径&#xff0c;运行模式以后&#xff0c;可以通过如下指令重启TFTP服务器&#xff0c;使设置生…

【Node.js】events

EventEmitter 像是 Vue2 的event bus&#xff0c;或者Vue3 的 mitt。主要采用了发布订阅模式来处理事件。 const EventEmitter require(events);const event new EventEmitter() // 监听(订阅)事件 event.on(test,(data)>{console.log(data) })event.emit(test,testtt) /…

Visual Studio 2013 - 高亮设置突出显示的引用

Visual Studio 2013 - 高亮设置突出显示的引用 1. 高亮设置 突出显示的引用References 1. 高亮设置 突出显示的引用 工具 -> 选项… -> 环境 -> 字体和颜色 References [1] Yongqiang Cheng, https://yongqiang.blog.csdn.net/

Flutter 事件传递简单概述、事件冒泡、事件穿透

前言 当前案例 Flutter SDK版本&#xff1a;3.13.2 本文对 事件传递只做 简单概述&#xff0c;主要讲解&#xff0c;事件传递过程中可能遇到的问题解决&#xff0c;比如 事件冒泡、事件穿透&#xff1b; 不是我偷懒&#xff0c;是自认为没有这几位写的详细、仔细&#xff0c…