您的位置:首页 > 移动开发 > Android开发

Android NDK开发之 NEON基础介绍

2015-12-30 14:04 537 查看
这是官方介绍:

http://www.arm.com/zh/products/processors/technologies/neon.php

一、NEON简介

ARM® NEON™ 通用 SIMD 引擎可有效处理当前和将来的多媒体格式,从而改善用户体验。

NEON 技术可加速多媒体和信号处理算法(如视频编码/解码、2D/3D 图形、游戏、音频和语音处理、图像处理技术、电话和声音合成),其性能至少为 ARMv5 性能的 3 倍,为 ARMv6 SIMD 性能的 2 倍。

通过干净方式构建的 NEON 技术可无缝用于其本身的独立管道和寄存器文件。
NEON 技术是 ARM
Cortex™-A 系列处理器的 128 位 SIMD(单指令,多数据)架构扩展,旨在为消费性多媒体应用程序提供灵活、强大的加速功能,从而显著改善用户体验。它具有 32 个寄存器,64 位宽(双倍视图为 16 个寄存器,128 位宽。)
NEON 指令可执行“打包的 SIMD”处理:

寄存器被视为同一数据类型元素矢量
数据类型可为:有符号/无符号的 8 位、16 位、32 位、64 位单精度浮点
指令在所有通道中执行同一操作



使用 NEON 技术的 ARM Cortex™-A 系列处理器,以及 ARM 的 Mali 多媒体硬件解决方案可用于多媒体应用,范围从智能手机移动计算设备到HDTV

下图通过SISD(单指令单数据)和SIMD(单指令多数据)的对比,来说明NEON的工作原理:



从图上可以看到,对于SISD,每个指令只能处理一个数据,而SIMD一个指令可以处理多个数据,因为多个数据的处理是平行的,因此从时间来说,一个指令执行的时间,SISD和SIMD是差不多的。由于SIMD一次可以处理N个数据,所以它的处理的时间也就缩短到SISD的1/N。
需要指出一点,NEON是需要硬件的支持的,需要有一块寄存器放到硬件上来处理这个的。
实际上ARM NEON的使用,是C方式调用,下面给出例子。

用C实现GRB灰度化算法



下面是一个用NEON现实的将GRB转化成灰度图的算法



对以上函数进行说明如下:



把权重放入NEON寄存器



一次载入8 pixles到三个NOEN寄存器,这个地方是重点可以说明NEON的高效率。



计算结果





NEON函数参考gcc工具里面的gcc.pdf文档中NEON部分.

二、选择NEON的原因

NEON增强了用户体验

观看任意格式的任意视频
编辑和强化捕获的视频 – 视频稳定性
锯齿消除渲染和合成
游戏处理
快速处理几百万像素的照片
语音识别
强大的多通道高保真音频处理

NEON的特征和优点

NEON 支持用于 Internet 应用程序的范围广泛的多媒体编解码器:

许多软编解码器标准:MPEG-4、H.264、On2 VP6/7/8、Real、AVS
对于各种格式的正常大小的“Internet 流”解码来说,是理想的解决方案
不仅仅针对编解码器,还适用于 2D 和 3D 图形和其他矢量处理
提供现有工具、操作系统支持生态体系支持

所需周期减少:

NEON 可使复杂视频编解码器的性能提升 60-150%
单个简单 DSP 算法可实现更大的性能提升(4 倍 -8 倍)
处理器可更快进入睡眠状态,从而在整体上节约了动态功耗

NEON 技术的大量元素能够提高性能并简化软件开发过程,如:

通过对齐和非对齐数据访问,可对 SIMD 操作进行有效的矢量化。
清晰的指令集架构,设计用于自动矢量化编译器和手动编码。
有效访问打包数组,如 ARGB 或 xyz 坐标
支持整数和浮点操作,以确保适合从编解码器、高性能计算到 3D 图形等广泛应用领域。
与 ARM 处理器紧密结合,提供单指令流和内存的统一视图,从而能够提供一个具有更简单工具流的开发平台目标。
通过具有双 128 位/64 位视图的大型 NEON 寄存器文件,可有效处理数据并尽可能减少对内存的访问,从而增加了数据吞吐量。

三、NEON应用

OpenMAX DL 库:

加速 AV 编解码器的建议方法
以源格式释放的库,在 ARM 网站上免费提供
支持以下格式:MPEG-4 简单配置文件、H.264 基准、JPEG、MP3、AAC
支持以下功能:FIR、IIR、FFT、点积、色彩空间转换、de-blocking.de-ringing、旋转、缩放、合成

矢量化编译器:

使用现有源代码自动搜索 NEON SIMD
受 ARM RealView 开发套件(v3.1 Pro 及更高版本)支持
在 2007q3 及更高版本中受 gcc 支持

C 内部函数:

C 函数调用接口至 NEON 操作
支持 NEON 支持的所有数据类型和操作
在 ARM RealView 开发套件(3.1 及更高版本)和 gcc 2007q3 及更高版本中受支持

汇编器:

针对确实需要在最低级别进行优化的用户
在 ARM 的
RealView 开发套件(3.1 及更高版本)和 gcc 2007q3 及更高版本中受支持

开源社区中的 NEON 支持

当前,在以下开源项目中支持 NEON:

Android – NEON 优化

使用 NEON,Skia 库 S32A_D565_Opaque 的速度加快了 5 倍

Ubuntu 09.04 支持 NEON:

关键共享库的 NEON 版本

Bluez – 官方 Linux 蓝牙协议堆栈

NEON SBC 音频编码器

Pixman(Cairo 2D 图形库的一部分)

合成/alpha 混合
X.Org、Mozilla Firefox、Fennec 和 Webkit 浏览器
例如,使用 NEON 后,fbCompositeSolidMask_nx8x0565neon 的速度提高了 8 倍

ffmpeg - libavcodec

用于众多 Linux 分发版的 LGPL 媒体播放器
视频:MPEG-2、MPEG-4ASP、H.264 (AVC)、VC1
音频:Ogg Vorbis

x264 – Google 2009 年度编程之夏

GPL h.264 编码器 – 例如,针对视频会议

【整理】SIMD、MMX、SSE、AVX、3D Now!、neon

SIMD

SIMD单指令流多数据流(SingleInstruction Multiple Data,SIMD)是一种采用一个控制器来控制多个处理器,同时对一组数据(又称“数据向量”)中的每一个分别执行相同的操作从而实现空间上的并行性的技术。在微处理器中,单指令流多数据流技术则是一个控制器控制多个平行的处理微元,例如Intel的MMX或SSE以及AMD的3D Now!技术。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------

MMX是由英特尔开发的一种SIMD多媒体指令集,共有57条指令。它于1996年集成在英特尔奔腾 (Pentium) MMX处理器上,以提高其多媒体数据的处理能力。

其优点是增加了处理器关于多媒体方面的处理能力,缺点是占用浮点数寄存器进行运算(64位MMX寄存器实际上就是浮点数寄存器的别名)以至于MMX 指令和浮点数操作不能同时工作。为了减少在MMX和浮点数模式切换之间所消耗的时间,程序员们尽可能减少模式切换的次数,也就是说,这两种操作在应用上是互斥的。后来英特尔在此基础上发展出SSE指令集;AMD在此基础上发展出3DNow!指令集。现在新开发的程序不再仅使用MMX来优化软件执行效能,而是改使用如SSE、3DNOW!等更容易优化效能的新一代多媒体指令集,不过目前的处理器仍可以执行针对MMX优化的较早期软件。

技术细节

MMX 寄存器,称作MM0到MM7,实际上就是处理器内部80比特字长的浮点寄存器栈st(0)到st(7)的尾数部分(64比特长)的复用。由于浮点栈寄存器的高16位未被MMX技术使用,因此这16位都置为1,因此从栈寄存器的角度看,其浮点值为NaN或Infinities,这可用于区分寄存器是处于浮点栈状态还是MMX状态. 作为MMX寄存器都是直接访问。利用了装配数据类型(packed data type)的概念,每个MMX寄存器的64比特字长可以看作是2个32位整数、或者4个16位整数、或者8个8位整数,从而可以执行整数SIMD运算。这对于1990年代中期的2D、3D计算的加速还是很有意义的,因为当时的计算机的图形处理器(GPU)还很不发达。但现在MMX整数SIMD运算对于图形运算来说是多余的技术了。不过MMX的饱和算术运算(saturationarithmeticoperations)对于一些数字信号处理应用还是有用的。

SIMD技术的发展

继 MMX技术之后,Intel又于1999年在Pentium-III处理器上推出SSE技术,引入了新的128比特宽的寄存器集 (register file),称作XMM0到XMM7。这些XMM寄存器用于4个单精度浮点数运算的SIMD执行,并可以与MMX整数运算或x87浮点运算混合执行。 2001年在Pentium 4上引入了SSE2技术,进一步扩展了指令集,使得XMM寄存器上可以执行8/16/32位宽的整数SIMD运算或双精度浮点数的SIMD运算。这使得 SIMD技术基本完善。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------

SSE

SSE(Streaming SIMD Extensions)是英特尔在AMD的3DNow!发布一年之后,在其计算机芯片Pentium III中引入的指令集,是继MMX的扩充指令集。SSE 指令集提供了 70 条新指令。AMD后来在Athlon XP中加入了对这个新指令集的支持。

目录

[隐藏]

1 SSE 的缓存器
2 SSE 指令表

2.1 浮点指令
2.2 整数指令
2.3 其他指令

3 后续版本

3.1 SSE2
3.2 SSE3
3.3 SSSE3
3.4 SSE4
3.5 SSE5
3.6 AVX
3.7 FMA

4 参见

SSE的缓存器

SSE 加入新的 8 个 128 位缓存器(XMM0~XMM7)。而 AMD 发表的x86-64延伸架构《又称 AMD64》再加入额外 8 个缓存器。除此之外还有一个新的 32 位的控制/状态缓存器(MXCSR)。不过只能在 64 位的模式下才能使用额外 8 个缓存器。

每 个缓存器可以容纳 4 个 32 位单精度浮点数,或是2 个 64 位双精度浮点数,或是 4 个 32 位整数,或是 8 个 16 位短整数,或是 16 个字符。整数运算能够使用正负号运算。而整数 SIMD 运算可能仍然要与 8 个 64 位 MMX 缓存器一起执行。

因为操作系统必须要在进程切换的时候保护这些 128 位的缓存器状态,除非操作系统去启动这些缓存器,否则默认值是不会去启用的。这表示操作系统必须要知道如何使用 FXSAVE 与 FXRSTOR 指令才能储存 x87 与 SSE 缓存器的状态。而在当时 IA-32 的主流操作系统很快的都加入了此功能。

由于 SSE 加入了浮点支持,SSE 就比MMX 更加常用。而 SSE2 加入了整数运算支持之后让SSE 更加的有弹性,当 MMX 变成是多余的指令集,SSE 指令集甚至可以与 MMX 并行运作,在某些时候可以提供额外的性能增进。

第一个支持 SSE 的 CPU 是 Pentium III,在FPU 与SSE 之间共享执行支持。当编译出来的软件能够交叉的同时以 FPU 与 SSE 运作,Pentium III 并无法在同一个周期中同时执行 FPU 与 SSE。这个限制降低了指令管线的有效性,不过 XMM 缓存器能够让 SIMD 与纯量浮点运算混合执行,而不会因为切换 MMX/浮点模式而产生性能的折损。

SSE指令表

SSE 提供纯量与包裹式(packed)浮点指令。

浮点指令

内存到缓存器/缓存器到内存/缓存器之间的数据搬移

纯量 – MOVSS
包裹式 – MOVAPS, MOVUPS, MOVLPS, MOVHPS, MOVLHPS, MOVHLPS

数学运算

纯量 – ADDSS, SUBSS, MULSS, DIVSS, RCPSS, SQRTSS, MAXSS, MINSS, RSQRTSS
包裹式 – ADDPS, SUBPS, MULPS, DIVPS, RCPPS, SQRTPS, MAXPS, MINPS, RSQRTPS

比较

纯量 – CMPSS, COMISS, UCOMISS
包裹式 – CMPPS

资料拆包(unpack)与随机搬移(shuffle)

包裹式 – SHUFPS, UNPCKHPS, UNPCKLPS

数据型态转换

纯量 – CVTSI2SS, CVTSS2SI, CVTTSS2SI
包裹式 – CVTPI2PS, CVTPS2PI, CVTTPS2PI

逐位逻辑运算

包裹式 – ANDPS, ORPS, XORPS, ANDNPS

整数指令

数学运算

PMULHUW, PSADBW, PAVGB, PAVGW, PMAXUB, PMINUB, PMAXSW, PMINSW

数据搬移

PEXTRW, PINSRW

其他

PMOVMSKB, PSHUFW

其他指令

MXCSR 管理

LDMXCSR, STMXCSR

快取与内存管理

MOVNTQ, MOVNTPS, MASKMOVQ, PREFETCH0, PREFETCH1, PREFETCH2, PREFETCHNTA, SFENCE

后续版本

SSE2

SSE2是 Intel在Pentium 4处理器的最初版本中引入的,但是AMD后来在Opteron 和Athlon64处理器中也加入了SSE2的支持。SSE2指令集添加了对64位双精度浮点数的支持,以及对整型数据的支持,也就是说这个指令集中所有的MMX指令都是多余的了,同时也避免了占用浮点数寄存器。这个指令集还增加了对CPU快取的控制指令。AMD对它的扩展增加了8个XMM寄存器,但是需要切换到64位 模式(x86-64/AMD64)才可以使用这些寄存器。Intel后来在其Intel 64架构中也增加了对x86-64的支持。

SSE3

SSE3是 Intel在Pentium 4处理器的 Prescott 核心中引入的第三代SIMD指令集,AMD在Athlon64的第五个版本,Venice核心中也加入了SSE3的支持。这个指令集扩展的指令包含寄存器的局部位之间的运算,例如高位和低位之间的加减运算;浮点数到整数的转换,以及对超线程技术的支持。

SSSE3

SSSE3是Intel针对SSE3指令集的一次额外扩充,最早内建于Core2 Duo处理器中。

SSE4

SSE4是Intel在Penryn核心的Core 2 Duo与Core2 Solo处理器时,新增的47条新多媒体指令集,并且现在更新至SSE4.2。AMD也开发了属于自己的SSE4a多媒体指令集,并内建在Phenom与 Opteron等K10架构处理器中,不过无法与Intel的SSE4系列指令集兼容。

SSE5

SSE5是AMD为了打破Intel垄断在处理器指令集的独霸地位所提出的,SSE5初期规划将加入超过100条新指令,其中最引人注目的就是三操作数指令(3-OperandInstructions)及熔合乘法累积(Fused Multiply Accumulate)。其中,三操作数指令让处理器可将一个数学或逻辑函式库,套用到操作数或输入数据。藉由增加操作数的数量,一个 x86 指令能处理二至三笔数据, SSE5 允许将多个简单指令汇整成一个指令,达到更有效率的指令处理模式。提升为三运算指令的运算能力,是少数RISC架构的水平。熔合乘法累积让允许建立新的指令,有效率地执行各种复杂的运算。熔合乘法累积可结合乘法与加法运算,透过单一指令执行多笔重复计算。透过简化程序码,让系统能迅速执行绘图着色、快速相片着色、音场音效,以及复杂向量演算等效能密集的应用作业。目前AMD已放弃下一代Bulldozer核心内建
SSE5指令集,改内建Intel授权SSE4系列指令集。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------

AVX

  是Sandy Bridge和Larrabee架构新指令集  Intel的微架构也进入了全速发展的时期,在2010年4月结束的IDF峰会上Intel公司就发布了 2010年的RoadMap。2011年1月Intel发布全新的处理器微架构Sandy Bridge,其中全新增加的指令集也将带来CPU性能的提升。

AVX(Advanced Vector Extensions) 是Intel的SSE延伸架构,如IA16至IA32般的把缓存器XMM 128bit提升至YMM 256bit,以增加一倍的运算效率。此架构支持了三运算指令(3-Operand Instructions),减少在编码上需要先复制才能运算的动作。在微码部分使用了LES LDS这两少用的指令作为延伸指令Prefix。

FMA

FMA是Intel的AVX扩充指令集,如名称上熔合乘法累积(Fused Multiply Accumulate)的意思一样。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------

3DNow!

3DNow!(据称是“3D No Waiting!”的缩写)是由AMD开发的一套SIMD多媒体指令集,支持单精度浮点数的矢量运算,用于增强x86架构的计算机在三维图像处理上的性能。

目录

[隐藏]

1 历史
2 支持检测
3 执行环境
4 3DNow!指令集

4.1 单精度浮点运算指令
4.2 增强的MMX指令
4.3 数据类型转换指令
4.4 数据预取指令
4.5 快速退出MMX状态指令

5 外部链接

历史

1996年Intel首先推出了支持MMX的Pentium处理器,极大地提高了CPU处理多媒体数据的能力,被广泛地应用于语音合成、语音识别、音频视频编解码、图像处理和串流媒体等领域。但是MMX只支持整数运算,浮点数运算仍然要使用传统的x87协处理器指令。由于MMX与x87的寄存器相互重叠,在MMX代码中插入x87指令时必须先执行EMMS指令清除MMX状态,频繁地切换状态将严重影响性能。这限制了MMX指令在需要大量浮点运算的程序,如三维几何变换、裁剪和投影中的应用。

另一方面,由于x87古怪的堆栈式缓存器结构,使得硬件上将其流水线化和软件上合理调度指令都很困难,这成为提高x86架构浮点性能的一个瓶颈。

为了解决以上这两个问题,AMD公司于1998年推出了包含21条指令的3DNow!指令集,并在其K6-2处理器中实现。K6-2是第一个能执行浮点SIMD指令的x86处理器,也是第一个支持水平浮点寄存器模型的x86处理器。借助3DNow!,K6-2实现了x86处理器上最快的浮点单元,在每个时钟周期内最多可得到4个单精度浮点数结果,是传统x87协处理器的4倍。许多游戏厂商为3DNow!优化了程序,微软的DirectX 7也为3DNow!做了优化,AMD处理器的游戏性能第一次超过Intel,这大大提升了AMD在消费者心目中的地位。K6-2和随后的K6-III成为市场上的热门货。

1999年,随着Athlon处理器的推出,AMD为3DNow!增加了5条新的指令,用于增强其在DSP方面的性能,它们被称为“扩展3DNow!”(Extended 3DNow!)。

为了对抗3DNow!,Intel公司于1999年推出了SSE指令集。SSE几乎能提供3DNow!的所有功能,而且能在一条指令中处理两倍多的单精度浮点数;同时,SSE完全支持IEEE 754,在处理单精度浮点数时可以完全代替x87。这迅速瓦解了3DNow!的优势。

1999年后,随着主流操作系统和软件都开始支持SSE并为SSE优化,AMD在其2000年发布的代号为“Thunderbird”的 Athlon处理器中添加了对SSE的完全支持(“经典”的Athlon或K7只支持SSE中与MMX有关的部分,AMD称之为“扩展MMX”即 Extended MMX)。随后,AMD致力于AMD64架构的开发;在SIMD指令集方面,AMD跟随Intel,为自己的处理器添加SSE2和SSE3支持,而不再改进3DNow!。

2010年八月,AMD宣布将在新一代处理器中取消除了两条数据预取指令之外3DNow!指令的支持,并鼓励开发者将3DNow!代码重新用SSE实现。

支持检测

支持3DNow!的CPU的CPUID扩展功能字(EAX=80000001h时执行CPUID指令得到的EDX的内容)的(从低位到高位)第31位为1。支持扩展3DNow!的CPU的CPUID扩展功能字的(从低位到高位)第30位为1。

K6-2以后AMD所有的x86处理器都支持3DNow!,包括最新的Athlon 64、Opteron和Sempron处理器;Cyrix等一些其他厂家生产的某些处理器也支持3DNow!;但Intel生产的所有处理器都不支持3DNow!。

执行环境

3DNow!指令的执行环境与MMX一样,都是将8个x87寄存器ST0~ST7的低64位重命名为MMX寄存器MM0~MM7,并依平坦模式进行操作(即指令可以任意访问这8个寄存器中的任何一个而不必使用堆栈)。

由于3DNow!使用的寄存器与x87寄存器重叠,任务切换时,保存x87寄存器状态的同时也保存了3DNow!的状态,所以3DNow!不需要操作系统的额外支持。只要CPU支持3DNow!,含有3DNow!代码的程序可以在只考虑到x87状态的原有的操作系统上不加修改地运行。

由于3DNow!依平坦模式访问寄存器,对3DNow!浮点单元的管线化变得容易,这也利于编译器生成高效的浮点代码。

3DNow!指令集

3DNow!和扩展3DNow!的26条指令从功能上可以分为以下五类。

单精度浮点运算指令

此类指令的操作数均为64位,其高32位和低32位分别是IEEE754格式的单精度浮点数。大部分指令一次可接受两个这样的操作数,并得到两个单精度浮点数的结果。它们的汇编语言助记符都以PF开头。

3DNow!还包含有计算单精度倒数和开方倒数的指令,并可以依程序需要,得到12位精度和24位精度的结果。这些指令一次只能处理一个单精度浮点数。

3DNow!的一个特色是可以将同一寄存器内的64位操作数中的两个单精度浮点数相加或相乘,这在复数运算和内积运算中非常有用。Intel直到最近才在SSE3指令集中增加了这项功能,称之为“水平操作”。

为了保证与旧有操作系统的兼容性,与MMX指令一样,3DNow!指令不引发任何算术异常。3DNow!指令不会生成也不能正确处理NaN和非规格化数,也不支持指定舍入模式。因此3DNow!并不是IEEE 754的一个完整实现,即使是只涉及单精度浮点数时也不能完全代替x87。

增强的MMX指令

PAVGUSB用于求64位紧缩字节(8×8位字节)的平均值,可用于视频编码中的像素平均和图像缩放等。可能是意识到这个功能的重要性,Intel在SSE中添加了功能完全相同的PAVGB指令。

PMULHRW则用来补充MMX指令PMULHW的不足,在紧缩字(4×16位字)相乘时可以得到比后者更准确的结果。Intel直到最近才在SSSE3中增加了功能相似的指令PMULHRSW。

PSWAPD指令用于交换紧缩双字(2×32位字)中两个双字数据的位置。

数据类型转换指令

PF2ID、PI2FD等4条指令用于完成整数和单精度浮点数之间的相互转换。

数据预取指令

PREFETCH/PREFETCHW指令用于把将要使用到的数据从主存储器提前加载快取中,以减少访问主存储器的指令执行时的延迟。Intel在SSE中添加了类似的PREFETCHTx指令

快速退出MMX状态指令

FEMMS指令与MMX中的EMMS功能相同,用于退出MMX状态。在K6-2和K6-III处理器中,FEMMS比EMMS更快;在Athlon及更新的处理器中,FEMMS等同于EMMS。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: