【图像处理】NEON编程1 - 加载及存储

来源:互联网 发布:百度的端口号 编辑:程序博客网 时间:2024/05/22 12:58

介绍

这一系列来自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.

0 0
原创粉丝点击