一、simd
arm neon 是适用于 arm cortex-a 和 cortex-r 系列处理器的一种 simd(single instruction multiple data)扩展架构。
simd 采用一个控制器来控制多个处理器,同时对一组数据(又称“数据向量”)中的每个数据分别执行相同操作,从而实现并行技术。
simd 特别适用于一些常见的任务,如音频图像处理。大部分现代 cpu 设计都包含了 simd 指令,来提高多媒体使用的性能。
simd 操作示意图
如上图所示,标量运算时一次只能对一对数据执行乘法操作,而采用 simd 乘法指令,则一次可以对四对数据同时执行乘法操作。
a. 指令流与数据流
费林分类法根据指令流(instruction)和数据流(data)的处理方式进行分类,可分成四种计算机类型:
费林分类示意图
1. sisd(single instruction single data)
机器的硬件不支持任何形式的并行计算,所有的指令都是串行执行。单个核心执行单个指令流 , 操作存储在单个内存中的数据 , 每次一个操作。早期的计算机都是sisd机器,如冯诺.依曼架构,ibm pc机等。
2. misd(multiple instruction single data)
是采用多个指令流来处理单个数据流。由于实际情况中,采用多指令流处理多数据流才是更有效的方法,因此misd只是作为理论模型出现,没有投入到实际应用之中。
3. mimd(mutiple instruction mutiple data)
计算机具有多个异步和独立工作的处理器。在任何时钟周期内,不同的处理器可以在不同的数据片段上执行不同的指令,也即是同时执行多个指令流,而这些指令流分别对不同数据流进行操作。mimd架构可以用于诸如计算机辅助设计、计算机辅助制造、仿真、建模、通信交换机的多个应用领域。
除了以上模型外,由nvidia公司生产的gpu引入simt体系结构:
4. simt(single instruction multiple threads)
类似 cpu 上的多线程,所有的核心各有各的执行单元,数据不同,执行的命令是相同的。多个线程各有各的处理单元,和 simd 共用一个 alu 不同。
simt 示意图
b. simd 特点及发展趋势
1. simd 优势与不足
2. simd发展趋势
以arm架构下的下一代 simd 指令集 sve(scalable vector extension,可扩展矢量指令)为例,其是_针对高性能计算(hpc)和机器学习等领域开发的一套全新的矢量指令集_。
sve 指令集中有很多概念与 neon 指令集类似,例如矢量、通道、数据元素等。
sve指令集也提出了一个全新的概念:可变矢量长度编程模型。
sve 可扩展模型
传统的 simd 指令集采用固定大小的向量寄存器,例如 neon 指令集采用固定的 64/128 位长度的矢量寄存器。
而支持 vla 编程模型的 sve 指令集则支持可变长度的矢量寄存器。因此允许芯片设计者根据负载和成本来选择一个合适的矢量长度。
sve 指令集的矢量寄存器的长度最小支持 128 位,最大可以支持 2048 位,以 128 位为增量。sve 设计确保同一个应用程序可以在支持不同矢量长度的 sve 指令机器上运行,而不需要重新编译代码。
arm 在 2019 年便推出了 sve2,以最新的 armv9 为基础,扩充了更多的运算类型以全面替代 neon,同时增加了矩阵相关运算的支持。
二、 arm 的 simd 指令集
1. arm 处理器的 simd 支持 - neon
arm neon 单元默认包含在 cortex-a7 和 cortex-a15 处理器中,但在其他 armv7 cortex-a 系列处理器中是可选的,某些实现 armv7–a 或 armv7–r 架构配置文件的cortex-a 系列处理器可能不包含neon单元。
符合 armv7 的内核的可能组合有以下四种:
因此必须首先确认处理器是否支持 neon 和 vfp。可以在编译和运行的时候进行检查。
neon 发展史
2. arm 处理器的 simd 支持检查
2.1 编译阶段检查
检测 neon 单元是否存在的最简单方法。在 arm 编译器工具链(armcc)v4.0 及更高版本或 gcc 中,检查预定义宏 arm_neon 或者 __arm_neon 是否开启。
armasm 等效的预定义宏是 target_feature_neon。
2.2 运行阶段检查
在运行时检测 neon 单元需要操作系统的帮助。arm 架构有意不向用户模式应用程序公开处理器功能。在linux下,/proc/cpuinfo 以可读的形式包含此信息,比如:
在tegra(带有fpu的双核cortex-a9处理器)
$ /proc/cpuinfo swp half thumb fastmult vfp edsp thumbee vfpv3 vfpv3d16 带有 neon 单元的 arm cortex-a9 处理器
$ /proc/cpuinfo swp half thumb fastmult vfp edsp thumbee neon vfpv3 由于 /proc/cpuinfo 输出是基于文本的,因此通常首选查看辅助向量 /proc/self/auxv,其包含二进制格式的内核 hwcap,可以轻松地在 /proc/self/auxv 文件中搜索 at_hwcap 记录,以检查 hwcap_neon 位(4096)。
某些 linux 发行版 ld.so 链接器脚本被修改为通过 glibc 读取 hwcap ,并为启用 neon 的共享库添加额外的搜索路径。
3. 指令集关系
在armv7中,neon 与 vfp 指令集具有以下关系:
具有 neon 单元但没有vfp单元的处理器无法在硬件中执行浮点运算。
由于 neon simd 操作更有效地执行向量计算,因此从 armv7 的引入开始,vfp 单元中的向量模式操作已被弃用。因此,vfp 单元有时也称为浮点单元(fpu)。
vfp 可以提供完全兼容 ieee-754 的浮点运算,armv7 neon 单元中的单精度运算不完全符合 ieee-754。
neon不能取代 vfp。vfp 提供了一些在 neon 指令集中没有等效实现的专用指令。
半精度指令仅适用于包含半精度扩展的 neon 和 vfp 系统。
在armv8中,vfp已被neon取代,以上问题如 neon 并不完全符合 ieee 754 标准,并且有一些指令 vfp 支持而 neon 不支持的问题已在 armv8 中得到解决。
三、neon
neon 是适用于 arm cortex-a 系列处理器的一种128位 simd 扩展结构,每个处理器核心均有一个 neon 单元,因此可以实现多线程并行的加速效果。
1. neon基本原理
1.1 neon 指令执行流程
上图为 neon 单元完成加速计算的流程图。其中向量寄存器中的每个元素同步执行计算,以此来加速计算过程。
1.2 neon 计算资源
neon 与 arm 处理器资源关系
- neon 单元作为 arm指令集的扩展,使用独立于 arm 原有寄存器的 64位 或 128 位寄存器进行 simd 处理,在 64位 寄存器的寄存器文件上运行。
- neon 和 vfp 单元完全集成到了处理器中,并共享处理器资源以进行整数运算、循环控制和缓存。
与硬件加速器相比,这显着降低了面积和功耗成本。并且其还使用更简单的编程模型,因为neon 单元使用与应用程序相同的地址空间。
neon 与 vfp 资源关系
neon 寄存器与 vfp 寄存器重叠,armv7 有 32 个 neon d 寄存器,如下图所示。
neon 寄存器
2. neon指令
2.1 自动矢量化
向量化编译器可以使用 c 或 c++ 源代码,以一种能够有效使用 neo n硬件的方式对其进行矢量化。这意味着可以通过编写可移植的 c 代码,同时仍然可以获得 neon 指令所带来的性能水平。
为了帮助矢量化,将循环迭代次数设为矢量长度的倍数。gcc 和 arm 编译器工具链都具有为 neon 技术启用自动矢量化的选项。
2.2 neon汇编
对于性能要求特别高的程序,手工编写汇编代码是更适合的方式。
gnu 汇编器(gas) 和 arm compile r工具链汇编器(armasm)都支持 neon 指令的汇编。
编写汇编函数时,需要了解 arm eabi,其定义了如何使用寄存器。arm嵌入式应用程序二进制接口(eabi)指定哪些寄存器用于传递参数、返回结果或必须保留,指定了除arm内核寄存器之外的32个d寄存器的使用。下图对寄存器功能进行了总结。
寄存器功能
2.3 neon intrinsics
neon intrinsic 函数提供了一种编写 neon 代码的方法,该方法比汇编代码更易于维护,同时仍然可以控制生成的 neon 指令。
内部函数使用与 d 和 q neon 寄存器对应的新数据类型。数据类型支持创建直接映射到neon 寄存器的 c 变量。
neon intrinsic 函数的编写类似于使用这些变量作为参数或返回值的函数调用。编译器做了一些通常与编写汇编语言相关的繁重工作,例如:
寄存器分配
代码调度或重新排序指令
intrinsic 缺点
无法让编译器准确输出想要的代码,因此在转向neon汇编代码时仍有一些改进的可能性。
neon 指令简类型
neon 数据处理指令可以分为正常指令、长指令、宽指令、窄指令和饱和指令。
以 intrinsic 的长指令为例 int16x8_t vaddl_s8(int8x8_t __a, int8x8_t __b);
- 上面的函数将两个64位的 d 寄存器向量(每个向量包含8个8位数字)相加,生成一个包含8个16位数字的向量(存储在128位的q寄存器中),从而避免相加的结果溢出。
四、其他 simd 技术
1. 其他平台上的 simd 技术
simd 处理不是 arm 独有的,下图将其与 x86 和 altivec 进行了比较。
simd 对比
2. 与专用 dsp 对比
许多基于 arm 的 soc 中还包含 dsp 等协处理硬件,因此可以同时包含 neon 单元和dsp。相对于 dsp,neon 的特点有:
五、总结
本节主要介绍基本 simd 及其他的指令流与数据流的处理方式,neon 的基本原理、指令以及与其他平台及硬件的对比。
单通道LED高压线性恒流驱动IC无需变压器芯片方案推荐:SM2082D
基于区块链的数据共享如何驱动AI网络
人工智能落地应用 覆盖社会生活多个领域
华为荣耀10与V10的区别
纳米线晶体管能自我修复 有助研制单芯片飞船
从CPU优化技术层面讲解Arm NEON
2017款奔驰GLE400的配置参数,预售价75万起!
iphone8发布iphone7会降价吗?iphone8上市时间曝光:iPhone7价格将再跌,入手时期到了吗?
AW36612系列同步降压LED驱动芯片产品特点
利用MEMS扫描镜技术提高汽车安全性
米达部落培养高端区块链人才,实现百万年薪不是梦
手机零部件有哪些 手机芯片由什么组成
2020年5G进入高峰期将成为三大运营商未来的取胜关键
如何在三星Galaxy手机上启用暗模式
某政府大楼安防视频监控系统的解决方案
OPB_AHB桥接器的功能特性和如何实现应用设计
云服务器和网络服务器之间的区别是怎样的
正激电路工作原理波形分析
如何使用电阻器来解决限流问题?
PCB设计中有哪些实用的设置和其他成功秘诀?