从x86到ARM平台软件迁移实战

孙浩

2020 年 7 月 17 日

从x86到ARM平台软件迁移实战

从 x86 架构到 ARM 架构,计算产业的未来已经渐渐明晰,而鲲鹏作为先行者,生态的力量也愈发强大,始终秉持着“硬件开放、软件开源、使能伙伴”的初心,定将逐渐发展成为滋养新计算产业的一方沃土。


算力的“竞赛”在云计算、人工智能场景需求推动下,早已持续多年。单台服务器处理器性能的提升一直是最基本的算力提升单元,这也是当下 ARM 平台能够引流算力平台发展的原因。开发者通过从 x86 平台向 ARM 平台的迁移,既可以获得产品性能的提升,也能够降低使用成本,满足多场景应用需求。


比起以往,最近经常在项目中优先使用华为鲲鹏 ARM 处理器的服务器环境,也接触了大量的迁移项目需求。从这点变化来看,ARM 架构平台已经开始受到开发者的追捧。基于 ARM 架构设计的华为鲲鹏处理器,其实早早地便看到了未来计算机算力架构的迭代之路。多年来华为一直致力突破传统的老计算框架和计算平台,打造一个全新的全栈计算框架。在中国,华为不光会携手合作伙伴共建鲲鹏生态,为更多企业带来价值,更为重要的是,它还会带领我们融入全球 ARM 生态,共同推进 ARM 进阶为下一代计算机平台的实施标准。


2020 年 7 月 11 日,【18 城鲲鹏创新中心开发者创享日-中原鲲鹏生态创新中心专场】正式来开了帷幕,在此专场下华为的技术专家重点分享了代码迁移的实践案例及调优实战案例。


以下为内容解读:


进行软件迁移的必要性



如上图所示,整个计算机的计算基础架构包含底层的晶体管、物理原材料、微架构、自评级架构以及操作系统所完成的二进制机器译码汇编高级语言、Java、C 等等,整个技术栈从复杂到抽象,其技术语言也从一个简单的交换指令变化为汇编进行访存、锁存以及形成机器码,这个过程中最核心的变化在指令集上。想要成功运行,底层计算平台就必须能够支持该 CPU 的指令才可以。



如上图所示,x86 和鲲鹏使用的指令是不同的。简单来说,在鲲鹏上使用的是精简指令集,而在 x86 上使用的是相对复杂的指令集,另外 x86 和鲲鹏处理器在架构和向量寄存器上也存在差异。一个在 x86 上运行的程序根本不可能毫无阻碍地就在鲲鹏上使用,必须经过编译、优化才行。


从 x86 到鲲鹏,代码迁移的操作步骤


华为鲲鹏团队通过大量的项目迁移实践,结合自身平台需求,将软件迁移步骤归纳为以下五步:



1、迁移准备,收集硬件信息和软件栈信息为主;


2、迁移分析,对收集到的信息和软件栈做初步分析,判断需要迁移的模块代码,评估迁移的工作量;


3、编译迁移,分析完成之后就可以着手迁移工作,主要分为代码迁移和软件包迁移;


4、性能调优,验证完成之后对性能指标进行测试,进行性能调优;


5、测试与认证,保障商用上线。涉及压力测试、长稳测试、规模商用。


迁移案例实战


此外编译型语言项目迁移会相对复杂一点,所涉及的修改点也更多,因为代码中有可能蕴含一些指令集相关的宏定义或者功能性函数,需要重新编译。但是对于 Java/Python 这种解释型语言项目而言迁移难度就会大大降低,不过也需注意要按指导步骤规范迁移,以减少问题的产生。如果是纯 Java/Python 的程序,那么代码就无须做编译,因为本身的虚拟机已经对指令级进行了屏蔽,只要更换虚拟机即可。但是对 C 语言开发的项目而言就会相对复杂很多。


C 语言工程 ShengBTE 迁移案例


ShengBTE 是一款用于计算晶体热传导率的专业应用,它是由 C 语言以及一些相关数学计算库所开发完成的。



做任何事情的第一步都是要先查询官方文档以查找源码获取、编译方法和相关的一些依赖栈信息,该项目主要有 MPI、MKL 和 SPG 这三个依赖。MPI 是一个基于 GCC 的编译器,MKL 是因特尔深度优化之后的数学计算库,SPG 是一个开源的科学计算库,下面针对这这三个依赖库做兼容性分析。


先分析 MPI 和 SGP 这两个比较简单的。现阶段 MPI 官方推荐使用的是因特尔 MPI,由于因特尔的 MPI 在鲲鹏平台是不兼容的,所以在鲲鹏上最优选择使用 OPEN MPI;其次 SPG 是一个开源的数学计算库,在鲲鹏平台可以直接安装使用,它的安装方法与在 x86 平台是完全一致的,安装完即可正常使用。


最大的困难点是关于 MKL 的移植。MKL 是针对因特尔芯片实现深度优化的数学计算库,在鲲鹏平台是不兼容的。在真实的实践中,首先需要使用 spglib 进行替换,经过一系列测试之后发现还是缺少复本函数,导致此路不通。之后再尝试使用 Openblas 进行替换,还修改了 ShengBTE 的编译脚本,重新编译安装——运行正常,进而完成了对 ShengBTE 的整体移植。



上图显示了对编译脚本的具体修改,左边是官方提供的编译脚本,右边是经过迁移之后的编译脚本。这里涉及到的修改主要有三点:编译器的、编译选项、相关的编译库。编译器官方推荐的是因特尔的 NPI,而这里采用的是 Open NPI,不过这两者由于调用命令都是 NPIF90,所以修改都比较简单。但是因特尔 NPI 有特有的编译选项,OpenNPI 的编译选项是无法使用的,所以对其进行了屏蔽。还有相关依赖库的迁移,这里使用 Openblas 替代了 MKL 相关库,对相关的链接选项进行了修改,相关修改可以看上图。



通过以上我们可以看出,该案例的整体迁移有三个关键节点:


1、迁移准备,获取依赖信息。结合 Makefile、Python 等相关网站的资料,通过官方文档获取软件的依赖信息。


2、迁移分析,获取到这些信息之后,我们需要对它进行分析,分析出不兼容的依赖,找出移植的方法。


3、编译迁移,付诸实践。移植依赖,将依赖库迁移到鲲鹏平台下。


鲲鹏软件性能调优


代码迁移完成之后,下面很重要的一件事情便是对代码性能进行调优。



对于一个 4800×4800 的矩阵乘法,通过软件层算法调优,计算耗时从 6 万多秒下降到了 47 秒,运算速度提升了 1200 多倍,再次经过硬件层的调优,在鲲鹏处理器上 2 秒钟便完成了运算。在鲲鹏平台上经过软件、硬件层的性能调优,某些场景下可以实现代码性能万倍的提升,其重要性不言而喻。


性能调优的常用策略


1、CPU/内存、磁盘、网卡、应用软件是项目中性能调优的四个方向。


当计算器需要和外部交互的时候,需要输入、输出设备,像我们的网卡就是其中之一。由冯诺依曼架构及程序实现原理来看,影响硬件性能的因素主要有 CPU/内存、网卡、磁盘,在这些硬件之上的应用算法是否合理也是性能的一个关键点。


鲲鹏芯片对 NUMA 的架构进行了优化加速,应用层可以通过设置进程的亲和性,来指定进程在哪个 Core 上面运行、使用哪那个 NUMA 节点的内存,进而实现性能提升。



Process1 运行在 NUMA0 节点上的 Core0 里面,在没有指定内存分配策略的情况下,系统会根据各个 NUMA 的内存余量情况对内存做均衡分配,这种分配策略会导致 Process1 所使用的内存部分在 NUMA0 上面,另外一部分在 NUMA1 上;而同样运行在 MUMA 节点 1 上面的进程也会出现类似的内存分配情况。很显然这样的内存分配策略会让 Process1 访问的 NUMA 节点 1 的内存时延变大,进而使整体性能下降。那么应该如何规避这种情况呢?这里可以利用系统提供的 NUMA-Aware,也就是俗称的绑核,将进程 1 的内存优先从 NUMA0 上面去分配,这样进程访问的内存距离是最短的,相较于一开始的内存分配性能有了较大的提升。


2、充分采集性能指标,分析性能瓶颈,优化相关代码。


结合性能指标分析结果,合理选择使用平台加速库来优化代码的使用方案。



鲲鹏处理器除了提供硬件加速能力之外,还提供了基于鲲鹏加速指令开发的九大加速库,像 glibc 和 Hyerscan 是非常常用的基础库,glibc 用于内存管理,Hyerscan 是一个高性能的表达匹配库。在压缩场景中,鲲鹏也有相应的加速库,同样可以带来不少的性能提升。鲲鹏为加解密场景提供了 OpenSSL 的加速库,在 ISA、AES 等加密算法上使用了现代化的方法进行了优化,尤其是在 ISA 的性能上面提升是非常明显的。在多媒体的场景下,提供了视频的转码解码加速库,比如 X265、HMPP,目前已经有不少的 ISV 在尝试着使用,效果提升也比较明显。


3、充分利用硬件的资源,发挥软件的最优性能。


鲲鹏处理器在核数量上的优势,可以使其 CPU 利用率大大提升。随着内存价格的降低,服务器现在可以搭配更高的内存,可以配置 1T 甚至更多,内存的读写速度是远高于磁盘的,在这种内存充裕的情况下面,可以将更多的数据读取到内存,从而提升数据访问的性能。对于磁盘而言,其带宽是有限,磁盘出现堵塞的时候或者用堵塞方式操作磁盘都会影响它的性能,使用异步 IO 读写的方法,可以减少在磁盘 IO 上面的等待时间。软件调优的本质就是充分发挥硬件的性能。


4、对于网卡,寻找时延和吞吐量间的平衡点。



网卡中断在性能调优上是一个比较关键的点。网卡中断涉及两个关键参数,一个是 frames,一个是 Usecs。frames 表示网卡收到多少包后产生一次硬中断,usecs 表示网卡每隔多少微秒产生一次硬中断。降低网卡中断的频率可以大大提高 CPU 的利用率,以释放更多的 CPU 的时间片给业务使用。在数据库 TPCC 的测试模型中,我们实现了 10%的吞吐提升。


鲲鹏开发套件


以上实战讲了这么多,会不会感觉操作起来会有点累?不用担心,授人以渔之后,华为鲲鹏还授人以鱼。


华为鲲鹏为代码迁移提供了完善的开发套件,鲲鹏开发套件主要有三大工具:


1.分析扫描工具,分析扫描工具主要是自动扫描及分析一些安装包,源代码文件,提供迁移建议并且提供应用迁移和总体评估报告。


2.代码迁移工具,主要是覆盖一些常用语法、指令、机制差异、函数替换,可以解决 90%的 C/C+的迁移问题,同时也可以解决 50%的汇编代码的迁移问题。


3.性能优化工具,性能优化工具主要是在鲲鹏计算平台之上,通过采集系统的数据,分析出系统的性能瓶颈,定位到性能的瓶颈点及热点函数,给出性能调优的建议。


对于开发者而言,实实在在的生产力提升是最大的诱惑力,而华为鲲鹏做到了。华为鲲鹏处理器算力的效率已经在引领性能潮流。抓住华为构建鲲鹏生态的契机,实践业务软件的平台迁移无疑是现在最佳的选择。


从 x86 架构到 ARM 架构,计算产业的未来已经渐渐明晰,而鲲鹏作为先行者,生态的力量也愈发强大,始终秉持着“硬件开放、软件开源、使能伙伴”的初心,定将逐渐发展成为滋养新计算产业的一方沃土。


鲲鹏应用创新大赛 2020


华为为了支持鲲鹏生态的蓬勃发展,于 2020 年 7 月 2 日启动了“黄河鲲鹏开发者大赛——2020 鲲鹏应用创新大赛”,报名截止时间为 2020 年 8 月 12 日。


本次大赛旨在激发行业创新、促进人才培养、加速产业融合,吸引全产业开发者共同打造鲲鹏全栈解决方案,实现技术与商业创新应用。大赛设置省级奖金 115 万元,国家级奖金 500 万元,参赛获奖作品更有免费方案宣传推广等众多权益获取机会。鲲鹏展翅九万里,长空无崖任搏击,河南的小伙伴们,作为河南赛区的种子选手,扫描下方二维码开始报名吧!



2020 年 7 月 17 日 09:38944

评论

发布
暂无评论
发现更多内容

Spring Security入门到实践(一)HTTP Basic在Spring Security中的应用原理浅析

独钓寒江雪

源码分析 spring security

程序员面试必备战衣 | T恤衫 - 程序员穿搭

chaozh

GEEK

每个现代人都应该知道的包豪斯| 艺术

chaozh

【干货分享】通过命令操作来学习Git

独钓寒江雪

git git入门

架构师训练营 - 命题作业 第 7 周

铁血杰克

压测工具如何选择?

elfkingw

JVM 类加载机制

Alex🐒

JVM 深入理解JVM

深入理解 JS 中的变量提升

Verlime

JavaScript 前端

Java并行程序基础

独钓寒江雪

Java 高并发 并行

JVM 垃圾回收机制

Alex🐒

JVM 深入理解JVM

架构师训练营第7周总结

时来运转

深入Java Web技术内幕(一)浅析Web请求过程

独钓寒江雪

Java web

女娲造物与补天 | 中国古神话

chaozh

深入理解 JS 参数传递

Verlime

JavaScript 前端

架构师训练营第七周作业-性能测试

sunnywhy

优雅地利用c++编程从1乘到20 | 技术总结

chaozh

c++

深入 Java Web 技术内幕(二)浅析DNS域名解析过程

独钓寒江雪

DNS 域名解析

人民自己创造的节日 | 经济

chaozh

彻底弄懂C++11右值引用 | 技术总结

chaozh

c++

深入理解 JS 中的 this

Verlime

JavaScript 前端

Flask 中的 Sessions

Leetao

Python flask Web框架

架构师训练营第7周作业

时来运转

JVM 对象内存布局

Alex🐒

JVM 深入理解JVM

Ubuntu 20.04 上安装和配置 VNC

酱紫的小白兔

创世 | 中国古神话

chaozh

神话

神国统治者 | 中国古神话

chaozh

如何挑选编程笔记本 | 数码产品

chaozh

JVM 运行时数据区

Alex🐒

JVM 深入理解JVM

JVM 垃圾回收器 CMS

Alex🐒

JVM 深入理解JVM GC

JVM 垃圾回收器 G1

Alex🐒

JVM 深入理解JVM GC

腾讯的背水一战还是奋力一搏? | 互联网

chaozh

从x86到ARM平台软件迁移实战-InfoQ