webooru icon indicating copy to clipboard operation
webooru copied to clipboard

ARM NEON优化(一)——NEON简介及基本架构 - Orchid Blog

Open madobet opened this issue 4 years ago • 0 comments

本文旨在介绍 ARMv7 开始增加的一项 advanced SIMD extension——NEON 技术。有助于帮助读者理解 NEON 概况,提供的实例分析有助于迅速上手 NEON 编程。阅读此文要求读者有基本的C/C++ 经验汇编代码经验,若没有也没关系,多理解查阅资料即可。Good luck~!

Catalog

  1. SIMD 及 NEON 概览
  2. NEON 架构(寄存器 / 数据类型 / 指令集)

SIMD 及 NEON 概览

SIMD

Single Instruction Multiple Data (SIMD)顾名思义就是 “一条指令处理多个数据(一般是以 2 为底的指数数量)” 的并行处理技术,相比于 “一条指令处理几个数据”,运算速度将会大大提高。它是 Michael J. Flynn 在 1966 年定义的四种计算机架构之一(根据指令数与数据流的关系定义,其余还有 SISD、MISD、MIMD)。

许多程序需要处理大量的数据集,而且很多都是由少于 32bits 的位数来存储的。比如在视频、图形、图像处理中的 8-bit 像素数据;音频编码中的 16-bit 采样数据等。在诸如上述的情形中,很可能充斥着大量简单而重复的运算,且少有控制代码的出现。因此,SIMD 就擅长为这类程序提供更高的性能,比如下面几类:

  • Block-based data processing.
  • Audio, video, and image processing codes.
  • 2D graphics based on rectangular blocks of pixels.
  • 3D graphics.
  • Color-space conversion.
  • Physics simulations.

在 32-bit 内核的处理器上,如 Cortex-A 系列,如果不采用 SIMD 则会将大量时间花费在处理 8-bit 或 16-bit 的数据上,但是处理器本身的 ALU、寄存器、数据深度又是主要为了 32-bit 的运算而设计的。因此 NEON 应运而生。

NEON

NEON 就是一种基于 SIMD 思想的 ARM 技术,相比于 ARMv6 或之前的架构,**NEON 结合了 64-bit 和 128-bit 的 SIMD 指令集,提供 128-bit 宽的向量运算 (vector operations)。**NEON 技术从 ARMv7 开始被采用,目前可以在 ARM Cortex-A 和 Cortex-R 系列处理器中采用。

NEON 在 Cortex-A7、Cortex-A12、Cortex-A15 处理器中被设置为默认选项,但是在其余的 ARMv7 Cortex-A 系列中是可选项。NEON 与 VFP 共享了同样的寄存器,但它具有自己独立的执行流水线。


NEON 架构(数据类型 / 寄存器 / 指令集)

NEON 支持的数据类型

  • 32-bit single precision floating-point 32-bit 单精度浮点数;
  • 8, 16, 32 and 64-bit unsigned and signed integers 8, 16, 32 and 64-bit 无符号 / 有符号整型;
  • 8 and 16-bit polynomials 8 and 16-bit 多项式。

NEON 数据类型说明符:

  • Unsigned integer U8 U16 U32 U64
  • Signed integer S8 S16 S32 S64
  • Integer of unspecified type I8 I16 I32 I64
  • Floating-point number F16 F32
  • Polynomial over {0,1} P8

注:F16 不适用于数据处理运算,只用于数据转换,仅用于实现半精度体系结构扩展的系统。

多项式算术在实现某些加密、数据完整性算法中非常有用。

NEON 寄存器(重点)

NEON 寄存器有几种形式:

  • 16×128-bit 寄存器 (Q0-Q15);
  • 或 32×64-bit 寄存器 (D0-D31)
  • 或上述寄存器的组合。

注:每一个 Q0-Q15 寄存器映射到一对 D 寄存器。

寄存器之间的映射关系:

  • D<2n> 映射到 Q 的最低有效半部;
  • D<2n+1> 映射到 Q 的最高有效半部;

结合 NEON 支持的数据类型,NEON 寄存器有如下图的几种形态:

NEON 数据处理指令可分为:

  • Normal instructions can operate on any vector types, and produce result vectors the same size, and usually the same type, as the operand vectors.
  • Long instructions operate on doubleword vector operands and produce a quadword vector result.(操作双字 vectors,生成四倍长字 vectors) The result elements are usually twice the width of the operands, and of the same type.(结果的宽度一般比操作数加倍,同类型) Long instructions are specified using an L appended to the instruction.(在指令中加 L)
  • Wide instructions operate on a doubleword vector operand and a quadword vector operand, producing a quadword vector result.(操作双字 + 四倍长字,生成四倍长字) The result elements and the first operand are twice the width of the second operand elements.(结果和第一个操作数都是第二个操作数的两倍宽度) Wide instructions have a W appended to the instruction.(在指令中加 W)
  • Narrow instructions operate on quadword vector operands, and produce a doubleword vector result.(操作四倍长字,生成双字) The result elements are usually half the width of the operand elements.(结果宽度一般是操作数的一半) Narrow instructions are specified using an N appended to the instruction.(在指令中加 N)
  • Saturating variants
    • ARM 中的饱和算法:
      • 对于有符号饱和运算,如果结果小于 –2^n,则返回的结果将为 –2^n;
      • 对于无符号饱和运算,如果整个结果将是负值,那么返回的结果是 0;如果结果大于 2^n – 1,则返回的结果将为 2^n – 1;
    • NEON 中的饱和算法:通过在 V 和指令助记符之间使用 Q 前缀可以指定饱和指令,原理与上述内容相同。

下面给出几幅图解释上述指令的操作原理,图片来自Search Results Cortex-A Series Programmer’s Guide

NEON 指令集(重点)

ARMv7/AArch32 指令格式

所有的支持 NEON 指令都有一个助记符V,下面以 32 位指令为例,说明指令的一般格式:

V{<mod>}<op>{<shape>}{<cond>}{.<dt>}{<dest>}, src1, src2

    • Q: The instruction uses saturating arithmetic, so that the result is saturated within the range of the specified data type, such as VQABS, VQSHL etc.
    • H: The instruction will halve the result. It does this by shifting right by one place (effectively a divide by two with truncation), such as VHADD, VHSUB.
    • D: The instruction doubles the result, such as VQDMULL, VQDMLAL, VQDMLSL and VQ{R}DMULH.
    • R: The instruction will perform rounding on the result, equivalent to adding 0.5 to the result before truncating, such as VRHADD, VRSHR.
  • - the operation (for example, ADD, SUB, MUL).
  • - Shape,即前文中的 Long (L), Wide (W), Narrow (N).
  • - Condition, used with IT instruction.
  • <.dt> - Data type, such as s8, u8, f32 etc.
  • - Destination.
  • - Source operand 1.
  • - Source operand 2.

注: {} 表示可选的参数。

比如:

VADD.I16 D0, D1, D2   @ 16位加法
VMLAL.S16 Q2, D8, D9  @ 有符号16位乘加

NEON 支持的指令总结

  1. 运算:和、差、积、商
  2. 共享的 NEON 和 VFP 指令:涉及加载、多寄存器间的传送、存储

具体指令请参见ARM® Compiler armasm User Guide - Chapter 12 NEON and VFP Instructions

注:VFP 指令与 NEON 可能相像,助记符也可能与 NEON 指令相同,但是操作数等等是不同的,涉及多个基本运算。



https://zyddora.github.io/2016/02/28/neon_1/

madobet avatar Jun 09 '20 02:06 madobet