madobet / webooru

Web Danbooru
32 stars 6 forks source link

利用NEON技术编写代码 - 中文社区博客 - 中文社区 - Arm Community #218

Open madobet opened 4 years ago

madobet commented 4 years ago

For English version, please check: Coding Using NEON Technology.


利用 NEON 技术编写代码

投稿人:来宾合作伙伴博客, 2013 年 5 月 21 日

ARM NEON™ 技术广泛地用于多媒体优化。NEON 技术的 SIMD 架构使得其非常适合多媒体编解码器中的许多计算密集型模块,例如过滤和解块等。本文探索有效的代码编写技巧,提高音频 / 视频编解码器的性能。

多媒体编解码器中的压缩算法涉及对大块数据的处理。这些可能是简单的元素层面运算,作用于阵列或矩阵,或者迭代大块数据的更为复杂的循环。在许多情形中,代码可以重新组织,以便循环迭代可以高效而并行地执行。

在视频编解码器的情形中,大多数的处理是针对一个方块的行像素和列像素执行的。例如,循环内解块过滤器涉及对垂直和水平边缘的多个像素的数据处理。这些计算可以使用 NEON 技术以适当的方式组织数据来加速。以垂直过滤的情形为例。

NEON 加载和转置指令用于将一个列的所有 16 个像素(8 位深)加载到 Q 寄存器中。如上图所示,帧缓冲中一行的 8 个像素 P3,P2,P1,P0,Q0,Q1,Q2,Q3 加载到一个 D 寄存器中,并对其余 15 行执行类似的运算,每一行递增一个帧宽度。为了利用 NEON 指令,需要转置加载的行像素。矢量转置将其运算对象矢量的元素视作 2 x 2 矩阵,并转置这些矩阵。作为转置过程中的第一步,顶部 8 行像素应加载到 d0,d2,d4,d6,d8,d10,d12,d14 中,底部 8 行像应加载到 d1,d3,d5,d7,d9,d11,d13,d15 中。

顶部 8 行

VLD1.8 d0, [framebuffer], framewidth

VLD1.8 d2, [framebuffer], framewidth

VLD1.8 d4, [framebuffer], framewidth

VLD1.8 d6, [framebuffer], framewidth

VLD1.8 d8, [framebuffer], framewidth

VLD1.8 d10, [framebuffer], framewidth

VLD1.8 d12, [framebuffer], framewidth

VLD1.8 d14, [framebuffer], framewidth

底部 8 行

VLD1.8 d1, [framebuffer], framewidth

VLD1.8 d3, [framebuffer], framewidth

VLD1.8 d5, [framebuffer], framewidth

VLD1.8 d7, [framebuffer], framewidth

VLD1.8 d9, [framebuffer], framewidth

VLD1.8 d11, [framebuffer], framewidth

VLD1.8 d13, [framebuffer], framewidth

VLD1.8 d15, [framebuffer], framewidth

  1. VTRN.32、VTRN.16 和 VTRN.8 指令对 8 个 Q 寄存器(16 个 D 寄存器)进行运算,将每一列数据组织到一个 Q 寄存器中(共 8 个 Q 寄存器),如下所示:

将两个 Q 寄存器的 32 位分区视作 2X2 矩阵的元素,并对后续 Q 寄存器中的 2 个内部 2x2 矩阵执行转置。

  1. VTRN.32 Q0, Q4
  2. VTRN.32 Q1, Q5
  3. VTRN.32 Q2, Q6
  4. VTRN.32 Q3, Q7

将两个 Q 寄存器的 16 位分区视作 2X2 矩阵的元素,并对后续 Q 寄存器中的 4 个内部 2x2 矩阵执行转置。

  1. VTRN.16 Q0, Q2
  2. VTRN.16 Q1, Q3
  3. VTRN.16 Q4, Q6
  4. VTRN.16 Q5, Q7

将两个 Q 寄存器的 8 位分区视作 2X2 矩阵的元素,并对后续 Q 寄存器中的 8 个内部 2x2 矩阵执行转置。

  1. VTRN.8 Q0, Q1
  2. VTRN.8 Q2, Q3
  3. VTRN.8 Q4, Q5
  4. VTRN.8 Q6, Q7

为了平滑单个边缘,需要对 8 个 Q 寄存器执行过滤运算。考虑更新边缘像素 P0 的等式。

P0 = (P2+2P1+2P0+2Q0+Q1+4)>>3

一个边缘像素需要 4 次加法、3 次乘法,以及 1 个取整指令。在 NEON 中,这一运算在 Q 寄存器上执行,因此 16 个边缘像素通过 4 次加法、3 次乘法和 1 个取整指令获得更新。使用 NEON 指令实施这一模块使得周期数减少了 80%。

音频编解码器中的部分计算密集型模块也可以利用 NEON 有效编码,如立体声处理、FFT 和过滤等。对 NEON 功能的高效利用平均可在视频编解码器情形中减少 80% 周期数,在音频编解码器的情形中则可减少 40%。

由于视频处理中的数据元素是 8 位或 16 位,NEON 矢量指令和大型寄存器集合使得其非常适合数据并行计算。可以在较少的周期内加载 / 存储多个数据元素。此外,NEON 也支持对齐加载,可进一步用于减少周期数。NEON 支持的隔行加载 / 存储非常适合优化 FFT。

有关各种不同优化技巧和如何组织代码以利用 NEON 功能的更多信息,请参见:

  1. 利用 ARM NEON 优化多媒体编解码器”,其位于SoCtronics.com 上的 “媒体与下载” 下。
  2. 或者,直接从此处下载白皮书。

合作博客作者:

Vivek Arora 是 SoCtronics Technologies Pvt. Ltd. 的计划经理,负责客户计划和产品管理。他拥有计算机工程技术学士学位和 MBA 学位。他拥有大约 12 年的工作经验,主要是为跨国公司开发移动电话和定制嵌入式平台等产品。

ARM 欢迎 ARM 联合体 (CC) 的众多合作伙伴提交来宾博客,这些博客内容将在我们多个社区博客上发表。如果您有兴趣参与,请将咨询问题通过电邮发至 Tell.Us@arm.com

ARM 联合体 (CC) 是一个广泛的生态系统,涵盖了基于 ARM 处理器设计的各个方面,从芯片实现到系统及设备设计。CC 是一个合作创新的平台,提供多种类型的论坛,供成员彼此合作,接触客户,解决行业面临的挑战,令设计人员可以关注各种功能,缩短 ARM Powered 解决方案的上市时间。

https://community.arm.com/cn/b/blog/posts/neon