随着产业数字化时代的到来,以 AI 为核心的数字科技能力已经成为催生新一轮经济发展的新动能。作为数字化转型基础的计算平台创新,正在成为这个时期最强大的新型生产力。
按照 OpenAI 发布的研究,2012 年至 2018 年,人们对于算力的需求平均每年增长 10 倍,这种需求的增长已经超越了摩尔定律的极限。
算力是数字世界的动力。华为发布的《泛在算力》白皮书报告中指出,人均算力和国家的人均 GDP 强相关,已成为衡量一个国家一个地区经济发展的重要指标,算力投入将会带来巨大的乘数效应,比如在制造业,1 美元的算力投入可以带来 10 美元的最终产出,对经济发展起到推动作用。
华为聚焦鲲鹏计算产业。鲲鹏计算产业是基于鲲鹏处理器构建的全栈 IT 基础设施、行业应用及服务,包括鲲鹏 PC、鲲鹏服务器、存储、操作系统、中间件、虚拟化、数据库、云服务、行业应用以及咨询管理服务等。
华为作为鲲鹏计算产业的成员,聚焦于发展华为鲲鹏+昇腾双引擎芯片族,通过“硬件开放、软件开源、使能合作伙伴”,推动计算产业的发展。
如何利用鲲鹏软件做软件迁移,和我们合作的互联网合作伙伴的核心应用是怎么做迁移的?贵阳站 18 城鲲鹏创新中心开发者创享日活动给你答案。
以下内容由 InfoQ 编辑整理自贵阳站 18 城鲲鹏创新中心开发者创享日活动,由华为鲲鹏计算软件迁移调优高级工程师刘坤、华为鲲鹏计算的软件工程师覃璐瑶分享。
一、鲲鹏软件迁移概述
1.软件迁移的背景和其必要性
计算机是由软件和硬件组成的,要执行软件层的应用程序,就需要底层 CPU 支持由汇编器形成二进制的机器码(由指令和数据组成)去运行。因此就需要底层计算平台能够支持该 CPU 的指令,对于不同的处理器而言,它们能够支撑的指令也大不相同,这也是在 x86 和鲲鹏编译的区别之处。
X86 是变长的指令,有 24 位和 16 位的,鲲鹏处理器是定长 32 位的指令,由于这些指令集上面的差异,X86 平台上面编译生成的应用程序在我们鲲鹏处理器平台进行运行的时候需要进行重新编译。
2.迁移的五个步骤
1)迁移准备 – 收集软件栈信息,准备迁移环境
迁移分析主要指的是,对搜集到的软件栈信息打开进行详细分析,包括使用什么语言,是否有相应的 X86 依赖需要移植。
2)迁移分析 – 分析软件栈,指定迁移策略
迁移分析要做的,就是对收集到的信息和软件栈做初步分析,判断是否真正需要迁移,评估迁移的工作量。
3)编译迁移 – 软件编译打包,验证基本功能
主要分为两类,一类是代码迁移,一类是软件包迁移。代码迁移可以分为编译型语言和解释型语言,编译型语言修改点主要涉及代码修改、编译脚本修改、内联汇编修改以及不兼容指令,如 SSE Intrinsic 类加速指令。解释型语言,主要分为直接翻译,如纯解释型语言开发的应用程序,如果软件含依赖库,需要重新编译。
软件包迁移主要是我们对 RPM 进行重构,包括扫描软件包所依赖的依赖项,对这些依赖库获取源码进行重新编译、打包。
4)性能调优 – 利用五步法优化软件性能
在迁移完成之后需要对性能进行调优,有”建立基准—压力测试—确定瓶颈—实施优化—确认效果”五个步骤。
5)测试与认证:保证商用上线,共建鲲鹏生态
通过测试和论证保证迁移完后,性能正常达标,包括压力测试、长稳测试、鲲鹏展翅论证等。
测试的话会经过功能测试、性能测试、长稳测试,这些测试的最终目的都是为了保证规模的商用。这个其实还有一个就是鲲鹏展翅论证。在认证上面,截止 6 月 5 日,累计有 809 家行业伙伴获得鲲鹏展翅论证。
3.典型案例
列举一下互联网合作伙伴核心应用的迁移。看一下左边(图如下)软件栈,它使用的 OS 是 debianOS,小众的迁移系统,我们打了 30 多个补丁,主要是 C++的代码、少量的汇编和 java 代码,有 520 多行的源码文件。迁移过来涉及到 55 个依赖库需要移植,有 39 个编译问题,总共涉及到 195 行代码的修改。从工作量上来看,在环境准备阶段,我们主要花一、两个月时间做技术分析,包括编译所需环境部署和准备。在代码移植过程中,我们花了 2 个月时间,做 C++的代码和汇编语言的迁移,其中 JDK 的安装,编译开源的源码,对于依赖库的替换和重新编译。最后花 2 个月的时间做性能调优,经过调优后,我们整体的性能指标测试是优于原友商芯片的。
二、C/C++代码迁移
C/C++代码编译构建过程主要包括以下六步。
第一步,需要获取源码,如果是开源的代码,可通过 github 去获取相应的源码;
第二步,准备编译环境,这时我们需要安装对应的 GCC 版本;
第三步,使用源码中的 CMakelists.txt 或 configure 脚本生成 makefile 文件;
第四步,执行 makefile 编译可执行程序;
第五步,替换依赖库,重新译或替换依赖 X86 平台的 so 库;
第六步,将可执行程序安装部署到生产或测试系统。
三、java/python 代码迁移
1、Java 代码迁移-鲲鹏上迁移改动点
Java 运行过程中可能涉及的迁移改动点
Java 源码移植过程是这样的,首先安装 JDK,将 Java 源码通过 Java 编译器编译;其次,对被调用的 SO 库,我们需要替换成 aarch6464 版本;再次,在程序运营时,可能涉及到一些参数的修改。
2.针对迁移改动点的处理方法
安装合适的 JDK 版本,需要通过源码编译、部署得到。
包含 SO 库调用的 jar 包迁移方法,首先通过 Dependency Advisor 工具分析扫描 jar 包,识别出所依赖的 SO 库,然后下载 SO 库源码,随后安装编译环境比如说 Maven、GCC,然后设置编译选项-fsigned-char,之后可以编译 aarch64 版本的 SO 库,然后替换掉 SO 库,重新打包的 jar 包,这样得到的 jar 包是可以在鲲鹏平台上运行的。
最后一个迁移改动点。需要我们设置 JVM 参数,保证程序稳定快速的运行。
3.案例
下面我们通过案例,来看这些编译迁移改动点。
这个案例是我们做项目过程中遇到的问题,我们需要对鲲鹏容器进行 8 小时压测,在第三小时时,有四台鲲鹏容器全部出现了内存耗尽、服务主进程挂死的问题,遇到这样的问题,我们首先想到业务代码是不是存在内存泄露。这时为了验证这一点,我们把鲲鹏容器内存大小从 4G 提升到 8G,进行长稳测试。
如果我们业务代码确实存在内存泄露,即使给它 8G 内存,后面还是会出现 OOM,结果是,四台鲲鹏容器能够正常运行,没有出现挂死,这时我们得出结论,并不是业务代码导致的内存泄露。
随后我们分析了 ARM 和 X86 在 JVM 参数上的差异,全面对比了 JVM 参数以及版本信息,结果 JVM 版本是完全一致的,堆空间大小也是一致的,但是线程栈的大小不一致,ARM 上是 2M,X86 是 1M,因为线程站多了 1M,导致 450 个线程多占用了 450M 内存,超过了我们堆内存空间大小,触发了 OOM。
从这个案例我们总结到,ARM 服务器上默认的线程堆栈会更大,如果线程过多会导致比 X86 多占用一些内存,触发 OOM。这个时候我们建议,修改参数来减少线程栈的大小,或者扩充我们整体堆内存。
(二)Python 代码的迁移
Python 代码迁移改动点有哪些?首先是我们的 Python 版本,建议客户将 Python 环境升级到 Python3.X;其次,在含 C 模块或者全 C 模块的迁移上,可以通过 Porting Advisor 工具分析我们的源码,然后识别到依赖的 SO 库以及 C 代码,随后我们下载对应的研源码模块,安装 GCC 编译环境,配置-fsigend-char 编译选项,执行模块中的 setup.py 这个文件自动完成模块编译。编译完成后,自动绘完成 aarch64 版本库的替换,再将编译完成得到的模块安装到 site-package 的目录下,供其他的 Python 源码调用。
(三)maven 软件仓库的构建
如何在鲲鹏上使用鲲鹏 maven 软件仓来构建 maven 工程?
对熟悉 Java 的开发者,maven 已经不陌生了,我们需要用 maven 管理 Java 项目。Java 程序依赖着它的 jar 包,而把 jar 包重新下载编译是十分耗时,maven 的作用就是把所有的开源软件编辑成一个 jar 包放在 maven 仓库上,需要时直接在 maven 上调用,这也叫作.jar 的依赖管理。
jar 依赖的分类有分本地仓库、远程仓库和中央仓库。在构建 jar 包的过程中,首先需要查询本地仓库,本地仓库如果找不到就去远程仓找,第三步需要编译实现,并且验证该版本在鲲鹏上是否可用,如果不可用,则需要重新编译这个包,然后替换到本地的仓库,再重新构建,编译出可使用的版本。
有没有一种软件仓全部包含是鲲鹏平台的软件组件呢?有。鲲鹏 Maven 仓实质就是一个远程仓,里面有各种各样适用于鲲鹏平台的 jar 包,通过鲲鹏的 maven 软件仓我们可以很快速的构建我们的软件。在实际操作中,我们可以把鲲鹏的 maven 软件仓库放在首位,以便我们 maven 构建的时候优先下载鲲鹏平台的 jar 包。
有了我们鲲鹏的 maven 软件仓,软件的构建流程是怎样的?首先在构建时,同样查询本地仓库,看看是否有我们所依赖的 jar 包。如果本地仓没有,会从鲲鹏软件仓库下载相应的组件并保存到本地。有获得依赖的组件后,我们再进行编译构建,构建得到我们想要的 jar 包,我们用 Dependency Advisor(分析扫描工具)扫描依赖库,如果这时已经不存在 X86 依赖了,构建到此结束。如果依旧存在 X86 的依赖可以参照前面的方法进行下载源码编译,替换到本地仓的 jar 包。这个过程中鲲鹏 maven 软件仓的关键作用,我们可以从上面直接下载 ARM 的依赖文件,不需要重新编译。大大简化了我们的工作量。
四、软件包迁移
1.rpm 包的迁移过程
首先我们需要将 X86 的 rpm 包做扫描,然后识别到其中的有 X86 依赖的文件,扫描后,知道哪些文件是需要迁移的,这时要下载源码进行编译。如果这个 jar 包能鲲鹏 maven 软件仓上找到,可直接下载使用。如果 SO 库或者二进制找不到,需要在鲲鹏平台重新编译。接下来,我们需要对这些文件打包,首先我们要解压 X86 的 rpm 包,并且将 X86 的依赖文件,替换成我们前面生成鲲鹏平台的 rpm 包或者 jar 包,进行重新打包,打包完成后,我们对它进行验证,验证分为两步,首先对他使用我们 Dependency Advisor(分析扫描工具)工具进行扫描,扫描确认里面是不是含有 X86 依赖的文件,其次,我们可以对它进行安装验证,验证它能否在鲲鹏平台正常运行。经过这个流程我们可以把 X86rpm 包重构成鲲鹏的 rpm 包。
2. rpm 迁移实例
这里是一个实例,首先我们下载 X86 的软件包,放到 Portadmin 目录,这里是 Knox 软件,在 Porting Advisor(代码迁移工具)界面端输入 Knox 的 rpm 包的名称,点击软件包构建,可以看到很快软件包构建成功了。这样一个软件包是可以在我们鲲鹏平台上直接运行的,非常方便。
【附】鲲鹏应用创新大赛宣传内容
与此同时,华为鲲鹏应用创新大赛也在同步展开,大赛旨在激发行业创新、促进人才培养、加速产业融合,通过全国各鲲鹏生态创新中心的联合举办,吸引全产业开发者共同打造鲲鹏全栈解决方案,实现技术与商业创新应用。
此次大赛设计了 7 类赛题,将开展区域赛和全国总决赛两级赛事,设置 500 万奖金池。报名将在 8 月 7 号截止。
相关链接:
鲲鹏开发者大赛总专题页
https://www.huaweicloud.com/kunpeng/activity/kunpeng_competition20.html
报名链接
https://competition.huaweicloud.com/information/1000041275/introduction
评论