介绍
这一系列来自ARM社区上的Coding for NEON,这里主要翻译为中文以便后续理解参考。第一篇原文链接。
ARM公司的NEON技术是基于64或128位的SIMD架构设计的,用于提升多媒体及信号处理应用的性能,包括视频编解码、声频编解码,3D图形,语言及图像处理。
这篇文章是如何使用汇编语言编写NEON代码系列的第一篇,该系列将会覆盖NEON入门,高效应用及相关使用技巧提示。我们将会从内存操作开始,学习如何使用加载及存储指令。
一个例子
从一个实际的例子开始,现有24位的RGB图像,该图像的像素以R,G,B,R,G,B的形式存放在内存当中,现在我们想要进行一个简单的操作,将R通道及B通道分离。怎样用NEON来达到更高效的实现?
使用线性加载,将RGB数据直接从内存取出保存至寄存器的这种方法显得很笨拙。
交换通道的代码不再显得简洁,掩码、移位、组合。这不太可能做到高效。
NEON提供了结构加载及存储指令来解决这种情况。他们从内存中读取数据同时分离数据到不同的寄存器中。在这个例子中,我们能够使用VLD3来分离红绿蓝通道。
现在交换红蓝通道寄存器 (VSWP d0, d2),并且将数据写回到内存中。交错存储时,可使用类似的存储指令VST3
细节
概述
NEON结构加载指令从内存中读取数据到64bit的NEON寄存器,根据可选的是否交错读取。存储时也是类似,在写入内存之前,使数据交错。
语法
结构加载及存储指令有以下的语法,包括五个部分。
- 指令助记符VLD表示加载,VST表示存储。
- interleave pattern 交错类型,在每个结构中对应元素之间的间隔
- element type 元素类型,表示访问的元素的位数
- NEON registers 将要被读取或者写入的64位的NEON寄存器集合,可列出高达4个寄存器,取决于交错类型。
- ARM address register ARM地址寄存器,包含被访问的内存地址,该地址可以在访问后进行更新。
交错类型
该指令允许加载、储存及错位包含1到4个相同大小元素的数据结构,这些元素是NEON所常用的8、16或者32位。
- VLD1 是最简单的形式。它不交错的从内存中加载1到4个寄存器。当处理不需要交错的数组时可使用这个指令。
- VLD2 加载2或者4寄存器的数据,交错的加载奇数和偶数元素到这些寄存器中。当需要分离左声道及右声道数据时可使用这个指令。
- VLD3 加载3个寄存器并且进行数据交错。对于分离RGB像素十分有效。
- VLD4 加载4个寄存器并且进行数据交错。可用这个指令处理ARGB。
存储指令支持一样的选项,但是是在写入内存时进行数据交错。
数据类型
加载及存储交错元素是基于调用指令时声明的大小。例如,用VLD2.16加载两个NEON寄存器会使四个在第一个寄存器中的16bit元素及四个在第二个寄存器中的16bit元素,根据奇偶数的顺序分离到各自的寄存器中。
将元素大小修改为32bit会使一样的数据被加载,但交错的数据不同,虽然都是奇偶数的顺序。
元素大小同样影响着字节顺序处理。一般情况下,如果你定义了正确的元素大小进行加载和存储操作,数据将会被按照合适的顺序从内存中读取,同样的代码在大端小端系统中都能够正常工作。
最后,元素大小对指针对齐有影响。对齐到元素大小的情况通常都能够获得较好的性能,并且这可能是你目标操作系统的要求。例如,当加载32bit元素时,对齐第一个元素的地址到32bits。
单元素或者多元素
为了加载多个元素,结构加载能够从内存中交错的读取单个元素,然后既可以保存到一个NEON中的所有lane,又可以保存到单个lane中。
当你需要从内存中的零散数据创建一个向量时,后面那种形式是十分有效的。
存储指令是类似的情况,支持交错的写单个或者多个元素。
地址
定义地址时,结构加载及存储指令支持三种格式。
Register: [ {,:}]
最简单的格式,数据会被加载和存储到定义好的地址。Register with increment after: [{,:}]!
这种格式适用于在加载或者存储后更新指针,并准备好加载或存储下一个元素。指针的增量等于该指令读取或者写入的字节个数。Register with post-index: [{,:}],
在内存访问之后,指针会加上Rm中的值。当读取或者写入一组被固定跨度所分离的元素时,非常有效,如,读取图像中的同一列元素。
你也可以通过Rn定义指针对齐,用可选的:参数,这通常能够加速内存访问。
其他的加载及存储指令
NEON也提供了:
- VLDR and VSTR
加载及存储64位单寄存器 - VLDM and VSTM
加载64位的多个寄存器。从栈中存储及获取数据时很有用。
更多关于加载及存储的信息,参考: ARM Architecture Reference Manual.
详细的指令时钟周期信息,可参考: Technical Reference Manual for each core.