前言

ARM NEON技术是一种高级的单指令多数据的架构扩展的实现。它是一种64位和128位混合的SIMD技术,主要应用场景是音视频处理,图像视觉计算,信号处理应用等需要密集计算的场景。

NEON技术是作为ARM核心的一部分实现的,但是它拥有自己的执行流水线,以及和ARM核心寄存器库不通用的寄存器库。上篇文章中介绍NEON四种调用技术有提到编译器自动向量化技术,可将 C/C++ 代码自动转换为 NEON 指令,这可以大幅减少初学者的入门成本并可以借鉴编译器的优化为后面的指令优化作参考,目前大多数编译器都具有自动向量化的功能,将 C/C++ 代码自动替换为 SIMD 指令。

本文将从入门成本低的编译器优化手段揭开NEON自动向量化的面纱。

编译器支持

GCC和ARM编译工具链提供使能自动向量化的NEON技术的功能,但由于C和c++标准不包括并发性方面,你可能需要为编译器提供额外的信息以使NEON功能得到更大的发挥,所需的代码需改全部是代码语言标准的一部分,所以不会对代码的跨平台移植造成影响。当编译器能确定程序员的意图时,编译器能很好的进行矢量化编译,前提是你必须对编译器指定恰当的参数,下面就分各种情况来说明NEON的使能方式:

编译器

GCC,LLVM和ARM编译工具链提供自动向量化的NEON技术的功能,具体如下:

Arm 编译工具

armcc编译器

基于LLVM-clang,最初为高性能计算设计,针对linux下的用户应用程序开发
LLVM-clang 开源,基于LLVM架构的C/C++/Objective-C编译器前端
GCC GNU编译器套件,开源

编译器配置

自动向量化默认不会被启用,开发者需要向编译器提供允许自动向量化的配置来对自动向量化功能进行使用。

Arm cc编译器中使能自动向量化

--vectorize          使能矢量化
        --cpu 7-A/Cortex-A8  指定支持NEON功能的处理器架构
        -O2/-O3              指定优化级别
        -Otime               指定优化类型,时间优先

LLVM 开启自动向量化:

Android NDK 从 r13 开始以 clang 为默认编译器,本节通过 cmake 调用Android NDK r19c 工具链展示 clang 的自动向量化方法。使用 Android NDK 工具链使能自动向量化配置参数如下:

-fvectorize  启用自动向量化(-O2 及以上优化等级默认启用)

-O 自动向量化仅在 -O1 及以上优化等级生效 ,-O1、-O2 等

在 CMake 中配置自动向量化方式如下:

# method 1
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O1 -fvectorize")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O1 -fvectorize")# method 2
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2")

GCC编译工具自动矢量化

GCC编译器支持自动矢量化设置,如下:
        -ftree-vectorize
        -mfpu=neon
        -mcpu            指定支持NEON功能的处理器架构

注:若优化级别设定为-O3则意味着-ftree-vectorize被设定;如果你没有指定-mcpu选项,GCC编译器会指定为内部默认处理器架构。这样的话编译出的程序可能会运行缓慢或者直接不能运行。

# AArch32
arm-none-linux-gnueabihf-gcc -mcpu=cortex-a53 -mfpu=neon -ftree-vectorize -O2 myfile.c# AArch64
aarch64-none-linux-gnu-gcc -mcpu=cortex-a53 -ftree-vectorize -O2 myfile.c

自动向量化

自动向量化示例

原函数进行有无向量化操作后,生成的汇编指令如下:

void add (int * __restrict pa, int * __restrict pb, unsigned int n, int x){unsigned int i;for (i = 0; i < (n & ~3); i++)pa[i] = pb [i] + x;}

注:没有向量优化的代码全是ARM指令实现的,而进行向量优化的代码中有NEON指令用来加速数据的load,add,save等关键耗时操作。 编译器通过矢量化加载 (ldr -> vld1)、求和 (add -> vadd)以及保存 (str -> vst1)等指令,将每次循环中处理的数据变为 4 个,循环次数精简为之前的 1/4。

自动向量化核心

从编译技术上来说,自动向量化一般包含两部分:循环向量化(Loop vectorization)超字并行向量化(SLP,Superword-Level Parallelism vectorization,又称Basic block vectorization)

上面的函数里将代码优化成下面的函数即是自动向量化的核心处理,

循环向量化:将循环进行展开,增加循环中的执行代码来减少循环次数。如以下代码将循环次数精简到之前的1/4,将pa[i] = pb [i] + x展开增加减少3次循环代价

SLP 向量化:编译器将多个标量运算绑定到一起,使其成为向量运算。下图将四次标量运算替换为一次向量运算。

向量化规则

在C/C++语言中没有指定有关于NEON编程的语法,所以编译器不能安全地生成并行代码,开发者可能需要向编译器提供额外的信息以获取到最好的向量化收益。

基于一定的编程优化准则,可以更好的协助编译器完成自动向量化的工作,获得理想的性能状态。

向量化是以确保优化后的代码与非向量化的代码有相同的结果的方式进行的。在某些情况下,为了避免出现不正确的结果,可能需要手动调整代码,使其更适合于自动向量化。有时候开发者会尝试手动优化代码,这也可能导致无法向量化,比如循环展开、开启编译器优化等。

向量化的规则包括以下几个方面:

  • 简短的代码最容易实现优化
  • 避免在循环中使用带break语句的条件判断
  • 尽量使循环次数是2的幂且循环次数是固定常量
  • 循环内部的函数应该是内联函数
  • 尽量使用带索引的数组而不是指针且间接寻找是不支持向量化的
  • 使用 restrict 关键字来告诉编译器指针不引用内存的重叠区域
  • 避免循环之间的依赖性
  • 浮点数据处理自动向量化条件苛刻

向量化性能瓶颈

编译器自动向量化过程和生成代码的性能受到一些因素的影响:

  • 循环的组织方式
  • 数据的结构
  • 循环的迭代次数
  • 数组的类型
  • 多级内存的使用

大多数应用程序都需要反复的优化以便让编译器优化出性能最佳的代码,但理想总是显得过于丰满,受限于环境,代码等影响,往往无法获取最高性能。

总结

自动向量化是一种快速简单的使用NEON加速的方法,减少开发者的学习和入手成本,因为用C/C++代码编写既增强了代码阅读性也增加了可移植性。但其本身优化条件比较苛刻,需要代码具备很好的并行性,对一些复杂代码很难起作用。

所以想要榨干编译器,获取极致的优化性能就不能完全依赖编译器的不确定性,可将编译器优化作为参考,通过intrinsic甚至neon汇编进行编程才是终极之道。

大前端CPU优化技术--NEON自动向量化相关推荐

  1. 大前端CPU优化技术--NEON指令介绍

    前言 ARM NEON 可以提升音视频,图像,计算机视觉等计算密集型程序的性能,在上一篇大前端CPU优化技术--NEON技术的介绍中,我们知道一些编译器可以将 C/C++ 代码自动转换为 NEON 指 ...

  2. 大前端CPU优化技术--NEON intrinsics进阶

    前言 今天我们继续介绍NEON intrinsics的指令知识,上篇大前端CPU优化技术--NEON intrinsics开篇中已经介绍了部分指令的作用.本篇文章除了介绍指令还会附上场景示例,方便大家 ...

  3. 大前端CPU优化技术--NEON技术

    前言 在上一篇中我们讲了SIMD技术的基础和前世今生,可以结合上一篇文章一起看大前端CPU优化技术--SIMD技术.今天我们全局性地讲解下NEON技术​. 目前主流的移动设备以ARM v7和v8版本架 ...

  4. 大前端CPU优化技术--NEON编程优化技巧

    前言 在前面的文章中我们介绍了NEON的基础,NEON技术的全景,指令及NEON intrinsic指令,相信大家能通过前面的学习写一些简单的NEON程序.但要想写好一个性能高的NEON程序,远不止你 ...

  5. 浅谈大前端的代表技术及其影响,值得我们思考

    到底哪些是大前端的代表技术?从业务上来说,我认为终端 开发.网关设计.接口设计.桌面端的 工程化都可以算是大前端的业务范畴. 具体的技术,则是基于 HTML5.NodeJS 的通用技术,以及各平台的专 ...

  6. 前端SEO优化技术汇总

    一.title.alt.h1 title: 网站头部标签<head>下的title,网站名称 备注:这里为什么不说标签中的title属性,,虽然鼠标上移可以显示图片名字,但是它跟SEO没一 ...

  7. 前端18个月难度翻番?来这里把握大前端技术本质进展丨稀土开发者大会

    图片来源:pexels.com "别更新了,学不动了"向来是前端开发群体的切肤之痛: React 还没学明白,Vue 就出来了: Vue 2.0 还没上手,3.0 就发布了: No ...

  8. 林云会研究院参加“创新大前端 研发新思路”线下技术沙龙活动

    2022年9月25日,由凡泰极客主办.优姆领克协办的"创新大前端.研发新思路"线下技术沙龙活动在南山科技园桑达科技大厦蓝马咖啡成功举办,林云会数字经济研究院应邀出席活动,与业内资深 ...

  9. 聚焦“云开发圆桌论坛”,大前端Serverless大佬们释放了这些讯号!

    4月14日,由云加社区举办的TVP&腾讯云技术交流日云开发专场,暨"腾讯云-云开发圆桌论坛"在北京.深圳两地同步举行. 当天下午,一场主题为"基于大前端和node ...

最新文章

  1. ORACLE 12C 依然支持 bbed
  2. 《软件工程方法与实践》—— 导读
  3. window 添加环境变量
  4. CSS Grid 网格布局教程
  5. C#设计模式之4-原型模式
  6. c++ 哈希_Redis源码解析十一--Hash键实现Redis 哈希键命令实现(t_hash)
  7. python输入长和宽计算面_python案例1
  8. leangoo更换背景、设置颜色标签功能上线啦!
  9. yii2 复制一个应用需配置
  10. mysql碎片data free_浅析MySQL数据碎片的产生(data free)
  11. AP聚类算法(Affinity propagation Clustering Algorithm )
  12. android 极光IM集成及使用
  13. 记一次联想Y7000P安装黑apple系统地经历
  14. 无人驾驶5: 贝叶斯公式
  15. Go语言switch语句
  16. AUTOCAD——JOIN合并命令
  17. Ninth season twentieth episode,Joey held a celebrities party but did not invited his friends!!!!!!
  18. 行稳致远,进而有为——2020年 XAG发展展望
  19. 基于Java+Spring的图书管理系统详细设计和实现
  20. 逻辑回归优化算法总结一

热门文章

  1. [官方软件] Easy Sysprep v4.3.29.602 【系统封装部署利器】(2016.01.22)--skyfree大神...
  2. word插入visio 绘图——图形匹配画布大小
  3. 基于飞凌FETA40i-C核心板在光时域反射仪中的应用原理
  4. UDP/ICMP协议简介
  5. ObjectARX类库简介
  6. 在windows上部署IIS web服务
  7. QT中的setAttribute()用法
  8. 第14章-Spring AOP通知(Advice)详解
  9. Intellij IDEA插件--Key Promoter X
  10. 机器学习入门(浅谈L1和L2正则)