鲲鹏经典直播征文】+【毕昇编译器】编译优化与软硬协同释放鲲鹏澎湃算力

网友投稿 978 2022-05-30

一、背景知识——编译优化与软硬协同

编译器:将源程序(高级语言)转换为等价的机器语言

源代码(source code)→预处理器(preprocessor)→编译器(compiler)→目标代码(object code)→链接器(Linker)→可执行程序(executables)

编译优化:保留程序语义(正确性)的前提下,对程序进行等价变化,从而较少程序运行时间

软硬协同:在编译优化中适配/使能诸多硬件特性

HPC( High Performance Computing,高性能计算)领域主要是解决计算密集型、海量数据处理等业务的计算需求,如科学研究、气象预报、计算模拟等。如何提高计算能力、极致化应用性能成为当前 HPC 领域各大平台最关键的课题之一,编译器在其中发挥着至关重要的作用。

二、认识毕昇编译器

毕昇编译器是基于开源LLVM 10.0.1版本开发,并进行了优化和改进,同时将flang作为默认的Fortran语言前端编译器,是一种Linux下针对鲲鹏920的高性能编译器,其针对鲲鹏平台进行了深度优化的高性能编译器。除支持 LLVM 通用功能和优化外之外,对中端及后端的关键技术点进行了深度优化,对以下三个方面进行了增强,使得鲲鹏平台的强劲算力能够最大限度地得到释放。

高性能编译算法:编译深度优化,内存优化增强,自动矢量化等,大幅提升指令和数据呑吐量。

加速指令集:结合 NEON/SVE 等内嵌指令技术,深度优化指令编译和运行时库,发挥鲲鹏架构极致算力。

AI 迭代调优:内置 AI 自学习模型,自动优化编译配置,迭代提升程序性能,完成最优编译。

关键特性

支持鲲鹏微架构芯片及指令优化

通过软硬协同提供相较开源LLVM更高的性能

集成Auto-tuner特性支持编译器自动调优

运行平台:鲲鹏920硬件平台

操作系统:openEuler21.03、openEuler 20.03 (LTS)、CentOS 7.6、Ubuntu 18.04、Ubuntu 20、麒麟V10、UOS 20

注:详细的运行平台和操作系统对应关系请参见 兼容性查询工具

部分通用信息请参考LLVM的用户指导https://llvm.org/docs/UserGuides.html

相比GCC和icc,LLVM前端Clang对语法的检查更严谨,严格匹配语言标准,Clang的常见兼容性和可移植性问题,请参考开源官方文档https://clang.llvm.org/compatibility.html

支持的编程语言

LLVM是一种涵盖多种编程语言和目标处理器的编译器,毕昇编译器聚焦于对C、C++、Fortran语言的支持,利用LLVM的Clang作为C和C++的编译和驱动程序,Flang作为Fortran语言的编译和驱动程序。

1、C,C++程序

Clang不仅仅是可以将C, C++程序编译为LLVM中间表示的IR,它也是一个驱动程序,会调用所有以代码生成为目标的LLVM优化遍,直到生成最终的二进制文件。毕昇编译器提供了端到端编译程序所需的所有工具和库。

2、Fortran程序

Flang是专为LLVM集成而设计的Fortran前端,由两个组件flang1和flang2组成。它也是一个驱动程序,将源代码转换为LLVM IR,前端驱动程序将IR传输下去进行优化和目标代码生成。

毕昇编译器优化效果:Benchmark跑分、HPC典型应用性能提升

当前毕昇编译器已广泛应用于多种 HPC 典型场景,如气象、安防、流体力学等,性能优势已初步体现。毕昇编译器与鲲鹏芯片协同,充分发挥芯片的性能,提升鲲鹏硬件平台上业务的性能体验。

基于鲲鹏上编译器优化,SPEC CPU 2017 benchmark 跑分平均优于 GCC 20%以上

HPC 典型气象应用 WRF 优于 GCC 10%~20%

三、毕昇编译器典型优化场景及其优化原理

1、结构体内存布局优化——大幅提升缓存命中率,突破访存瓶颈

将结构体数组转换为数组结构体

结构体可以是显式的,也可以通过检查循环中的数组使用情况来推断它们

可见在 struct 中,data1 的使用率极高,而 data2 是不使用的。然而由于源代码中,数据的排布是以结构体数组的形式排布。按照一般编译器的编译方式,拿数据时每次都会将整个结构体放到 cache 里面,导致大量不参与计算的 data2 也被加载到了 cache 中,造成高速内存空间的浪费和性能的损耗。毕昇编译器会通过用户标记的结构体声明,或者通过自动检查循环中适合优化的内存场景,确认优化点。然后通过将结构体数组变为数组结构体的方式(如上图右),将有效数据紧凑排布,从而提高 cache 命中率和应用性能。经测试,此优化可以对 mcf 子项带来50%的性能提升。

2、结构体指针压缩优化——大幅降低内存使用,提升缓存命中率

使编译过程更加灵活和可控

细粒度编译控制,提供更多优化机会

将指针成员由8字节压缩至4字节,减小每个结构体node的内存体积。被压缩的域成员指针外提为全局结构体指针ps_head,ps变换为相对基址的偏移,将有效数据紧凑排布,从而大幅降低内存使用,提升 cache 命中率和应用性能。

3、软件预取——大幅提高程序性能,提升缓存命中率

(1)软件预取:通过插入预取指令提前从内存中读取所需数据

(2)预取的效果取决于“提前量”

数据太早到达→浪费宝贵的cache空间

数据太晚到达→仍需要等待访存过程

(3)如何计算“提前量"

循环大小

Cache line大小

访存延迟

(4)针对鲲鹏微架构特征调整软件预取参数

4、自动矢量化—计算效率提升的秘诀

使用矢量寄存器、矢量指令提高并行度

理论基础:SIMD(single instruction multiple data),一条指令可以处理多个数据

硬件基础:ARM NEON指令集扩展,32个128位的矢量寄存器,指令可以同时操作4*32或2*64的数据

软件基础:编译器针对NEON指令的分析和优化

鲲鹏平台支持 Armv8 NEON 矢量化指令集。当前支持32个128位的矢量寄存器,指令可以同时操作4*32或2*64的数据。毕昇编译器依托这种硬件优势做了大量优化,包括 SLP(superword-level parallelism) 矢量化和循环自动矢量化。

例如在 SPEC CPU 2017 benchmark 中处理视频流格式转换的x264子项中,毕昇编译器会自动识别并使用 uabd 和 udot 这类高效向量指令完成计算来替换标量指令,增大单时钟周期的数据处理量, 从而大幅提升计算效率。对于 x264 子项,这项优化可有效提升其30%的计算效率。

5、循环优化——帮助发现更多的优化机会

Loop unroll:将循环体复制多遍

减少分支跳转次数

帮助发现更多的优化机会

Loop (partial) unswitch:外提(减少)循化内条件判断

Loop fusion/distribution:将循环体合成一个/拆成多个

6、Autotuner—基于机器学习快速获取最优编译配置

如何获取性能最优编译选项是编译器使用中常见的问题,往往需要长时间的手动选项调优。为了减少这其中的工作量,使得用户能快速找到最优的优化选项,毕昇编译器自研了基于 ML 的自动搜索技术(ML-based Search) 的 Autotuner 工具。

一种自动化的迭代过程, 通过操作编译设置来优化给定程序,以实现最佳性能。它由两个组件配合完成,毕异编译器和Autotuner命令行工具。此功能不需要在源代码中注入pragma,而是允许用户在简单的yaml文件中指定优化配置,该文件包含优化信息及其相应的代码区域信息,包括名称和行号。此外,它还可以记录优化结果,以及可调优的代码区间并以yaml的形式导出。

与毕昇编译器进行交互:

根据编译器产生的可调优代码结构创建搜索空间(search space)

生成编译配置并调用编译器来编译源代码

操作调优参数以及应用搜索算法

自带的遗传算法

获取性能数据

引入基于ML的自动搜索技术(ML-basedSearch)

关键技术点:

1、知识库(Autotuner Database):根据静动态分析信息,建立知识库,支持决策系统进行优化

2、优化决策系统(Optimal configuration):根据热点和性能评估信息、知识库信息,综合考虑确定优化措施

【鲲鹏经典直播征文】+【毕昇编译器】编译优化与软硬协同释放鲲鹏澎湃算力

3、热点标记和性能评价:热点标记,瓶颈检测,性能评估

4、查找驱动(Feedback):将优化决策系统,反馈的优化建议

Autotuner 的调优流程由两个阶段组成:初始编译阶段(initial compilation)和调优阶段(tuning process),如下图所示:

初始编译阶段

初始编译阶段发生在调优开始之前,Autotuner首先会让编译器对目标程序代码做一次编译,在编译的过程中,毕昇编译器会生成一些包含所有可调优结构的YAML文件, 告诉我们在这个目标程序中哪些结构可以用来调优,比如文件(module), 函数(function), 循环(loop)。 例如,循环展开是编译器中最常见的优化方法之一,它通过多次复制循环体代码,达到增大指令调度的空间,减少循环分支指令的开销等优化效果。若以循环展开次数(unroll factor)为对象进行调优,编译器会在YAML文件中生成所有可被循环展开的循环作为可调优结构。

调优阶段

当可调优结构顺利生成之后,调优阶段便会开始:

Autotuner首先读取生成好的可调优结构的YAML 文件,从而产生对应的搜索空间,也就是生成针对每个可调优代码结构的具体的参数和范围;

调优阶段会根据设定的搜索算法尝试一组参数的值,生成一个YAML格式的编译配置文件(compilation config),从而让编译器编译目标程序代码产生二进制文件;

最后Autotuner将编译好的文件以用户定义的方式运行并取得性能信息作为反馈;

经过一定数量的迭代之后,Autotuner将找出最终的最优配置,生成最优编译配置文件,以YAML的形式储存。

简单来说,在初始编译阶段,编译器会通过用户指定的调优方向,对可调优的代码区间进行标记。在随后的调优阶段,Autotuner 会根据搜索算法对不同的优化区间生成不同的编译配置。然后使用此配置编译运行,并根据运行性能的反馈来迭代优化配置参数。最后经过给定迭代次数后找出最优配置供用户使用。在实践过程中,通过 Autotuner 对 Coremark Benchmark 进行调优可以获取5%以上的收益。

7、毕昇编译器Fortran前端:特性、架构与优化增强

(1)毕昇编译器Fortran语言前端基于Classic Flang构建,通过增强Classic Flang,支持如下特性:

支持F2003、F2008 (Coarray特性除外)语言标准

最高支持四倍浮点精度(real16)数据类型,15维数组数据类型,支持OpenMP4.0、OpenMP4.5并行化编程模型

支持DWARF4标准

多种Pragma引导语支持,如软件prefetch,omp simd,unroll,vector等

(2)多个Fortran内建函数的优化

maxloc/minloc/nint的内联

trim/lentrim采用更优算法

(3)内存分配优化,栈内存替挽堆内存

(4)为中后端提供更准确详细的信息来辅助优化

别名分析增强

过程间优化增强

四、毕昇编译器:新版本

1、毕昇编译器1.3.3版本已于2021.06.30正式发布,点击”毕昇编译器软件包下载”,下载后解压使用:毕昇编译器软件包下载

其中包含以下新特性:

支持基于Structure Peeling的特性增强及指针压缩优化

完善Fortran2003/2008语言特性

新增大量优化特性:支持unroll and jam,loop distribution优化增强,软件预取增强,静态分支优化改善,循环矢量化特性增强等

Autotuner特性增强与完善,改善调优时间

新增支持macOS 10.0及以上版本

支持申请并使用鲲鹏远程云调测环境

优化操作易用性

新增毕昇JDK安装部署功能

修复部分已知BUG

2、软件包下载

点击”毕昇编译器软件包下载”,下载后解压使用:毕昇编译器软件包下载

点击”毕昇编译器sha256”,用于对比完整性校验结果:毕昇编译器 sha256

3、参考文档

毕昇编译器用户指南

毕昇编译器Autotuner 特性指南

4、问题讨论

鲲鹏社区论坛,可发帖提问:https://bbs.huaweicloud.com/forum/forum-923-1.html

五、总结

针对不同的场景,不同的应用特点,使用不同的编译优化手段

编译优化的代价与收益权衡,需要综合考虑性能收益,代码体积,编译时间,可调试性等多方面因素

软硬件结合,通过软件及硬件的协同优化,最大化的发挥硬件算力

语言生态构建的持续性,语言标准的不断演进,及新特性支持

【参考】

【1】鲲鹏论坛编译器版块:https://bbs.huaweicloud.com/forum/forumdisplay-fid-928-orderby-lastpost-filter-typeid-typeid-1642.html

【2】鲲鹏开发套件:https://kunpeng.huawei.com/#/developer/devkit/

【3】鲲鹏首页:https://kunpeng.huawei.com

【4】【毕昇编译器】编译优化与软硬协同释放鲲鹏澎湃算力:https://bbs.huaweicloud.com/live/kunpeng_live/202105311500.html

ARM 高性能计算 鲲鹏

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:mindspore模型训练—混合精度算法
下一篇:浅谈Google蜘蛛抓取的工作原理(待更新)
相关文章