NEON优化:性能优化经验总结

news2025/1/23 7:26:13

NEON优化:性能优化经验总结

  • 1. 什么是 NEON
    • Arm Adv SIMD 历史
  • 2. 寄存器
  • 3. NEON 命名方式
  • 4. 优化技巧

Reference:

  1. NEON优化:性能优化经验总结
  2. NEON官方内联函数
  3. Arm NEON programming quick reference
  4. Learn the architecture - Neon programmers’ guide

在这里插入图片描述

1. 什么是 NEON

NEON 技术是用于 Arm Cortex-A 系列处理器的先进 SIMD(单指令多数据)架构。它可以加速多媒体和信号处理算法,如视频编码器/解码器、2D/3D图形、游戏、音频和语音处理、图像处理、电话和声音。

NEON 指令执行“打包 SIMD”处理:

  • 寄存器被认为是相同数据类型元素的向量
  • 数据类型支持:带符号/无符号 8 8 8 位, 16 16 16 位, 32 32 32 位, 64 64 64 位,ARM 32 32 32位平台上的单精度浮点数,ARM 64 64 64位平台上的单精度浮点数和双精度浮点数。
  • 指令在所有通道中执行相同的操作

Arm Adv SIMD 历史

Armv6Armv7-AArmv8-A AArch64
SIMD extensionNEONNEON
在32位通用ARM寄存器上操作独立的寄存器库,32x64位NEON寄存器独立的寄存器库,32x128位NEON寄存器
8位或16位整数8/16/32/64位整数8/16/32/64位整数
每条指令进行2x16位/4x8位操作单精度浮点数单精度浮点数、双精度浮点数
每条指令最多16x8位操作(16x4吧,待确认)每条指令最多16x8位操作

2. 寄存器

Armv7-A 和 AArch32 具有相同的通用 Arm 寄存器 - 16 x 32 16 x 32 16x32 位通用 Arm 寄存器(R0-R15)。

Armv7-A 和 AArch32 具有 32 x 64 位 NEON 寄存器(D0-D31)。这些寄存器也可以看作是 16 × 128 位寄存器(Quadword, Q0-Q15)。每个 Q0-Q15 寄存器映射到一对D寄存器,如下图所示。
在这里插入图片描述相比之下,AArch64 具有 31 31 31 64 64 64 位通用 Arm 寄存器和 1 1 1 个具有不同名称的特殊寄存器,这取决于使用它的上下文。这些寄存器可以被看作是 31 31 31 64 64 64 位寄存器(X0-X30)或 31 31 31 32 32 32 位寄存器(W0-W30)。

AArch64 具有 32 32 32 x 128 128 128 位 NEON 寄存器(V0-V31,Vector Registers)。这些寄存器也可以看作是 32 32 32Sn寄存器(Single-word Registers) 64 64 64Dn寄存器(Double-word Registers)

在这里插入图片描述(也就是说,V 寄存器有 128 位,D 寄存器 64 位,S寄存器 32 位,可以将 V 寄存器拆开使用)

3. NEON 命名方式

  • 变量命名方式:

    • baseWxLxN_t
      • base:是基础数据类型
      • W:是基础类型的宽度
      • L:是向量的长度
      • N:是向量数组的个数
    • uint8x16_tuint8x16x3_t
  • 函数命名方式:

    • ret v[p][q][r]name[u][n][q](args)
      • ret:返回值类型
      • v:表示vector
      • q:饱和运算,溢位后,为自动限制在数据类型的最大范围内
      • r:圆整操作
      • name:SIMD指令名称
      • u:unsigned
      • n:narrow
      • q:做后缀表示128位满位宽寄存器运算 quarter*32

4. 优化技巧

  • 热点函数涉及到大量 IO 读写操作时,数据的内存地址尽量与 NEON 数组或系统位数对齐,如32位对齐,可降低访问开销;

  • 重点优先搞 NEON 指令并行计算,能大幅降低开销;

  • 大部分的 NEON 问题会出在存取、移动指令的滥用、混乱使用上(neon的寄存器和普通arm的寄存器是分开,也就是说arm的普通指令和neon指令之间不可以有过多的数据交换,但是sse没有这个限制?待验证);

  • for 循环:

    • for (b = 0; b < num; b++)
    • 可改成 for (b = 0; b < num - 3; b += 4)
    • 或者 for (b = num - 1; b >= 3; b -= 4)
    • 需注意结尾不能整除的几个还是用非SIMD方式计算:
      • 原始:for (i = 0; i < size; i++);
      • 并行:for (i = 0; i < size - 3; i += 4);
      • 扫尾:for (; i < size; i ++)。
  • 数组索引取值:

    • 数组索引以及索引内部涉及运算的,尽量换成指针偏移加减来做;
    • 避免大范围索引跳跃,减少 cache miss
  • 内存使用:

    • 优先用局部变量,而非 malloc 堆内存,减少 cache miss;
    • 针对具体变量类型,手动 for 循环并行拷贝值,可能比 memcpy() 函数更高效,因为 memcpy 内部还涉及大量判断,以保证平台兼容性;
    • 用NEON指令时,4 路运算的数组(128位=16字节),内存地址最好要 16 字节对齐。
  • 指令运算

    • 矩阵乘场景,在不大幅增加寄存器变量的前提下,外部的A也最好并行多读几路数据进来,跟B的各列运算,减少B各列的读取次数;
    • 乘加指令,add 和 mul 可以合并为 mla,一条指令完成乘加操作。
  • C 语言编码级考虑

    • C 语言中一条事件的处理函数尽可能在一个源文件中(便于编译器自动向量化);
    • switchif else 快,而且代码整洁。
  • 深入理解计算机系统

    • 组织代码结构,善用 CPU 缓存,数据段/代码段连续可以提高 CPU 缓存命中率;
    • 极简函数时,尽量 inline 展开,减少函数调用栈的开销;
    • 消除不必要的存储器引用,如 for 循环中 *dest = *dest - nums[i],可用中间变量替换 *dest,for 循环后再赋值给 *dest,可减少 for 内的一次读写操作;
    • 简单的循环展开,编译器可以自己完成,优化选项 O2 及以上,或者命令 -funroll-loops(O2 及以上自带),可调用 gcc 进行循环展开;
    • 能用整型不用浮点,整数乘法/加法和浮点加法,只用一个周期,浮点乘法需要2个周期。
  • NEON 与 SSE 在寄存器处理数据时有一些区别。在 NEON 中,通常需要先将要处理的数据加载到 NEON 寄存器,然后执行 SIMD 操作。这与 SSE 有一些不同,因为 SSE 寄存器(XMM 寄存器)可以直接与内存交互(这一步可能格外耗时,需要特别注意)。在 NEON 中,加载数据到 NEON 寄存器通常包括以下步骤:

    1. 从内存加载数据到通用寄存器(通常是ARM通用寄存器)。
    2. 将数据从通用寄存器传送到 NEON 寄存器。

    然后,您可以在 NEON 寄存器上执行 SIMD 操作,例如矢量加法、矢量乘法等。

    这与 SSE 不同,因为 SSE 寄存器可以直接从内存加载数据,而不需要中间步骤。这可以在 SSE 指令中实现,而不需要将数据先加载到通用寄存器中。

    总之,NEON 需要额外的步骤来加载数据到寄存器,然后才能进行 SIMD 操作,而 SSE 可以更直接地在寄存器中操作数据。这是因为不同架构和指令集设计的差异。

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

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

相关文章

Windows server 2022(2023年9月 映像更新 - 20348.1970)安装测试

本文记录了Windows server 2022(2023年9月 映像更新 - 20348.1970)的安装测试过程。 一、检查ISO 简体中文 - Windows Server 2022&#xff08;2023年9月更新 - 20348.1970&#xff09; 内含版本&#xff08;Windows Server 2022 Standard、Windows Server 2022 Standard (D…

期权定价模型系列【6】:欧式期权、百慕大期权、美式期权的定价模型与对比【蒙特卡洛模拟、二叉树模型】

期权定价模型系列第6篇文章 1. 前言 对于欧式期权&#xff0c;最常用的是BS模型&#xff0c;此外&#xff0c;也可也用蒙特卡洛模拟方法求解欧式期权的价格。当然&#xff0c;对于美式期权&#xff0c;也同样可以用蒙特卡洛模拟方法来求解&#xff0c;一般对美式更多用的是二叉…

Kubernetes(K8s):未来云原生应用的引擎

文章目录 Kubernetes的核心概念和架构为什么K8s是构建云原生应用的首选工具&#xff1f;云原生应用的好处和挑战容器编排的重要性&#xff1a;Docker和KubernetesKubernetes生态系统&#xff1a;核心组件和附加工具实际应用&#xff1a;企业如何在生产环境中使用K8s未来展望&am…

基于大语言模型扬长避短架构服务

秘诀&#xff1a; 扬泛化之长&#xff0c; 避时延之短

Linux socket 字节序

socket介绍 字节序 验证什么字节序 #include<stdio.h> int main() {union {short value;char btypes[sizeof(short)];} test;test.value 0x0102;if(test.btypes[0] 1 && test.btypes[1] 2) {printf("大端字节序\n");}else{printf("小端字节序…

postman的使用

感觉自己对于postman 的使用其实还是入门级别的 因为新公司的都是微服务调用所以需要使用本地postman进行调用。 接口大概是这个样子&#xff0c;截图的最下面就是接口的具体情况了 首先看PostMapping判断是否是get或者post 然后RequestHeader参数就是为了在postman中添加head…

安卓玩机-----教你修改微信的启动图 让心中的“她“成为微信沟通的第一屏【仅供参考】

微信已经成为我们生活中必不可少的安装必装软件之一。但单调的启动第一屏让人感到乏味。那么今天只给大家做个教程演示是怎么修改这个启动第一屏、其实任何的app都可以进行修改图标 启动界面等等的操作。需要替换的图片可以任意选择&#xff0c;我前面很多博文介绍过apk的反编译…

Mac 电脑查看本地maven,及私有仓库的搭建与使用【nexus的配置与使用】

查看本地maven 查看状态如果要查看本地maven&#xff0c;使用命令行&#xff1a; mvn help:effective-settings 如下如localRepository标签 nexus下载 官网地址 解压后如下图 启动服务器/停止服务器 bin 目录下 执行命令&#xff1a; ./nexus start 如下图表面启动成功…

java常用API(Math,System,Runtime)

Math Math的常用方法 package myMath;public class myMath {public static void main(String[] args) {System.out.println(Math.abs(-99));//这个表示取绝对值的 打印结果为99//但是他有个bug.int最大取值范围是-2,147,483,648 到2,147,483,647System.out.println(Math.abs(-…

经典垃圾回收器

Serial收集器 Serial 是一种新生代的收集器。顾名思义“serial 串行”&#xff0c;它是一种单线程工作的收集器&#xff0c;它的“单线程”并不仅仅指的只有一个处理器或一个线程来实现垃圾的收集工作&#xff0c;更重要的是他在垃圾收集的过程中会暂停所有的用户线程&#xf…

算法通过村第九关-二分(中序遍历)黄金笔记|手撕二分

文章目录 前言1. 基本查找2. 二分查找与分治2.1 循环的方式2.2 递归的方式 3. 元素中的重复的二分查找总结 前言 提示&#xff1a;有些人&#xff0c;远看是灯塔&#xff0c;靠近是悬崖。 --任明信《别人》 二分查找是非常重要的算法之一&#xff0c;不仅要掌握&#xff0c;更要…

印章篆刻小程序商城的作用是什么

印章的需求度也有很高市场需求&#xff0c;处理办公印章外&#xff0c;还有艺术类的&#xff0c;而对爱好者来说&#xff0c;需要找到一家靠谱的品牌制作&#xff0c;包括材料、样式、内容等都有较高要求&#xff0c;线上可以接触到更多雕刻商家。 而对品牌来说&#xff0c;需…

常见应用层协议

一.HTTP&#xff08;超文本传输协议&#xff09; HTTP 和 HTTPS 二.FTP&#xff08;文件传输协议&#xff09; 三.SMTP&#xff08;简单邮件传输协议&#xff09; 四.POP3&#xff08;邮局协议版本3&#xff09; 五.IMAP&#xff08;互联网消息访问协议&#xff09; 六.DNS&am…

GitHub 基本操作

目录 1、创建库 2、上传项目 3、获取token 4、 删除库 1、创建库 登录github&#xff0c;点击“Create repository”创建库&#xff0c;点击右上方绿色的“New”&#xff0c;Repository name处填写你的项目名&#xff0c;可选“Add a README file"默认创建一个说明文…

基于SSM的保险业务管理系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

480万商品,如何架构商品治理平台?

说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;很多小伙伴拿高薪&#xff0c;完成架构的升级&#xff0c;进入架构师赛道&#xff0c;打开薪酬天花板。 最近有小伙伴拿到了一线互联网企业如京东、网易、微博、阿里、汽车之家、极兔、有赞、希音、百度、滴滴的架…

Fortinet 2023上半年全球威胁态势研究报告:勒索软件检测成下降趋势,针对性攻击持续升温

近日&#xff0c;专注于推动网络与安全融合的全球网络安全领导者Fortinet&#xff08;NASDAQ&#xff1a;FTNT&#xff09;&#xff0c;发布《2023上半年全球威胁态势研究报告》。报告显示&#xff0c;2023 年上半年勒索软件检出数量继续下降、高级持续性威胁&#xff08;APT&a…

机器人中的数值优化|【六】线性共轭梯度法,牛顿共轭梯度法

机器人中的数值优化|【六】线性共轭梯度法&#xff0c;牛顿共轭梯度法 往期回顾 机器人中的数值优化|【一】数值优化基础 机器人中的数值优化|【二】最速下降法&#xff0c;可行牛顿法的python实现&#xff0c;以Rosenbrock function为例 机器人中的数值优化|【三】无约束优化…

Spring Boot 3.0:构建下一代Java应用的新方法

文章目录 Spring Boot 3.0&#xff1a;一览1. **模块化应用程序**2. **更强大的自动化工具**3. **更强大的安全性**4. **更好的性能和扩展性** 如何开始使用Spring Boot 3.01. 安装Spring Boot CLI2. 创建新项目3. 配置应用程序4. 编写业务逻辑5. 测试应用程序6. 构建和部署 结…

DataGrip 恢复数据

DataGrip 恢复数据 准备数据库 create database chap02; use chap02;恢复数据 运行sql脚本方式恢复数据到刚刚创建的数据库 数据右键—> SQL Scripts —> Run SQL Script… 选择sql脚本