Coding Neon - Part1:Load and Stores

转自ARM官网 https://developer.arm.com/architectures/instruction-sets/simd-isas/neon

原文链接:[Coding for Neon - Part 1: Load and Stores]
https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/coding-for-neon—part-1-load-and-stores?_ga=2.76228754.624776649.1595923255-241183949.1595923255


目录:
Coding Neon - Part1:Load and Stores
Coding Neon - Part2:Dealing With Leftovers
Coding Neon - Part3:Matrix Multiplication
Coding Neon - Part4:Shifting Left and Right
Coding Neon - Part5:Rearranging Vectors



  Arm的Neon技术是一种64/128位混合SIMD架构,旨在加速多媒体和信号处理应用程序的性能,包括视频编解码、音频编解码、3D图形、语音和图像处理。👍
  本文是系列文章的第一部分,教大家如何用汇编语言为Neon编写SIMD(Single Instruction Multiple Data单指令集多数据)代码。本系列将涵盖Neon的入门、高效使用,以及为更有经验的码农提供指示。我们将从内存操作开始,以及如何使用灵活的加载和存储置换指令。


An Example

  给你一个24位的RGB图像,像素在内存中排列为RGBRGB...,现在需要做一个简单的图像处理操作,例如交换红色和蓝色通道。如何使用Neon高效地做到这一点?
  用一个加载操作将RGB数据从内存线性地拉到寄存器,这种交换红/蓝的方式看起来很愚蠢。
在这里插入图片描述
  对于这种RGB排列的输入,编写通道交换的代码不会很优雅,例如掩码(masks)、位移(shifting)、组合(combing)等,不太可能有效率。
  Neon提供了结构化加载和存储指令,为上述情况提供帮助。它们从内存中提取数据,将这些值同时分离到不同的寄存器中。对于这个例子你可以用VLD3指令,在加载红、绿、蓝的同时将它们拆分。
在这里插入图片描述
  然后使用指令VSWP d0, d2交换红色和蓝色寄存器,再用类似命名的存储指令(VST3),将交织后的数据写回内存。


The Details

Overview(概述)

  Neon结构将这些从内存中读取的数据,加载到64位Neon寄存器中,同时可以选择性地将数据交错(deinterleaving)(如上面的例子)。存储的工作原理也类似,在写入内存之前,再次交错(reinterleaving)来自寄存器的数据。
在这里插入图片描述


Syntax(语法)

  结构加载和存储指令的语法由5个部分组成。
在这里插入图片描述

  • 助记指令符(Instruction mnemonic)VLD表示加载,VST表示存储。
  • 数字交织模式(Interleave pattern),在每个结构中,对应元素之间的间隔。
  • 元素类型(Element type),指定被访问元素的位数。
  • 一组要读或者写的Neon寄存器列表(Neon register list),最多可以列出4个寄存器,主要看交织模式的选择。
  • Arm地址寄存器(Arm address register),包含了内存中要访问的地址。访问后可以更新地址。

Interleave Pattern(交错模式)

  指令可以用于加载、存储和解交错(deinterleave)一块结构,结构中包含1到4个大小相等的元素(也就是寄存器列表的数量?),这些元素通常是Neon支持的8、16、32位宽度数据。

  • VLD1,是最简单的形式,它从内存中加载1到4个寄存器的数据,没有解交错(deinterleaving)。处理一组没有交错(non-interleaved)的数据的时候使用这种模式。
  • VLD2,加载2到4个寄存器的数据,将偶数和奇数元素解交错(deinterleaving)到这些寄存器中。使用此选项可将立体声音频数据分为左右声道。
  • VLD3,加载3个寄存器的数据,并且解交错(deinterleaving),用于将RGB像素分割为通道。
  • VLD4,加载4个寄存器的数据,并且解交错(deinterleaving),用于处理ARGB的图像数据。

  存储指令支持同样的选项,并且在写入内存之前,交错(interleave)来自寄存器的数据。


Element Types(元素类型)

  根据指令指定的大小,加载或存储交错的元素。例如用VLD 2 .16加载2个Neon寄存器的数据,会在第一个寄存器中产生4个16位元素,在第二个寄存器中产生4个16位元素,相邻的一对(奇和偶)分离到每个寄存器中。(看图↓↓↓)

在这里插入图片描述
  若将元素大小改为32位(以上图为例把16位改成32位),则会加载同样数量的数据,但是每个Neon寄存器里面只有2个元素。另外,仍然像上面一样,同时又分为奇数和偶数元素。(看图↓↓↓)
在这里插入图片描述
  元素大小也会影响字节序处理。通常,如果为加载和存储指令指定了正确的元素大小,则将以适当的顺序从内存中读取字节,以同样的代码在大端或者小端系统上运行。(这段不知道想讲什么,反正要注意大小端系统的字节顺序)。
  最后,元素的大小会影响指针对齐。与元素大小对齐通常可以提供更好的性能,或者你的目标操作系统要求这样做。例如,加载32位元素的时候,第一个元素的地址至少对齐到32位。


Single or Multiple Elements(单个或多个元素)

  除了加载多个元素外,结构加载还可以通过解交错(deinterleaving)从内存中读取单个元素,将其读取到Neon寄存器的所有通道或者单个通道,而其它通道保持完整。
在这里插入图片描述
  当你需要根据分散在内存中的数据构造向量时,后一种形式很有用。
在这里插入图片描述
  存储也相似,通过交错(interleaving),为写入单个或多个元素提供支持。


Addressing(寻址)

  结构加载和存储指令支持3种形式,用于指定寻址。

  • 寄存器:[{,:}]
    这是最简单的形式,数据将会被加载或者存储到指定的地址。
  • 后面加个叹号:[{,:}]!
    这种方式在加载或存储数据后更新指针,准备加载或存储下一个元素。指针增量等于指令加载或存储的字节数。
  • 后面加个逗号:[{,:}],
    在内存访问后,指针的增量等于Rm寄存器的值。在读取或写入以固定宽度分隔的一组元素时,这种方式很有效。例如,读取一张图像中的垂直线。

  你还可以使用可选的“:”参数,为Rn寄存器中的指针指定对齐方式,这通常会加速内存访问。


Other Loads and Stores(其它加载和存储)

  在本文中,我们仅讲述了加载和存储,Neon还提供了:

  • VLDRVSTR
    加载和存储单个寄存器(以64位值)。
  • VLDMVSTM
    以64位值加载多个寄存器。对于从栈上存取寄存器很有用。

==============================================================

  有关支持的加载和存储操作的更多详细信息,请参见《 Arm Architecture参考手册》。 有关说明的详细循环计时信息,请参见每个内核的《技术参考手册》。


下一篇文章:Code for Neon - Part2:Dealing With Leftovers

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值