大规模基础建设托举着经济发展,以数字化技术主导的“新基建”开展得如火如荼。5G、数据中心、云计算、物联网、人工智能等新应用相继落地,市场需要多样化算力的支撑。然而作为全球计算产业发展的主要推动力和增长引擎之一,中国计算机产业正面临着重塑的新格局,亟需能够引领这一切的能力者。
华为坚持从“芯”到“魂”全面出击,在强大的技术底座支撑下,华为致力于将鲲鹏和昇腾打造成数字经济最强大的算力底座,为数字经济发展提供安全的、多样性的、充裕的、可持续性的算力。
7 月 11 日,在【 DevRun 开发者沙龙——18 城鲲鹏开发者创享日重庆站】上,华为线上为开发者分享了“鲲鹏迁移”的相关技术原理、实践经验和对应方法论,蓄力新生态下算力提升。
以下内容经由 InfoQ 编辑整理自【 DevRun 开发者沙龙——18 城鲲鹏开发者创享日重庆站】中刘坤和覃璐瑶老师的分享。
编译型语言迁移
高级语言通常分为编译型语言和解释型语言,典型的如 C/C++/Go 语言,都属于编译型语言。编译型语言开发的程序在从 x86 处理器迁移到鲲鹏处理器时,必须经过重新编译才能运行。举一个简单的例子,如下图所示,test.c 源码需要经过预处理生成件 test.i,再由编译器生成汇编代码文件 test.s,之后通过汇编器进一步汇编生成目标文件 test.o,但是它还不能进行运行,原因是其还需要链接外部所依赖的一些资源才能完成整个运行的过程,因此需要最后经过一个链接,生成可执行程序 test。
在 C,C++软件移植的过程当中,要着重考虑五个方面的问题:
编译脚本,编译选项移植:以 x86 下 -m64 代码为例,x86 下 -m64 代码的主要功能是将应用程序编译为 64 位,对应到鯤鹏上是用 -mabi=lp64 的编译选项,此类编译选项需要在脚本中修改,对应的 Cmakelists 里有可能存在 add_defin 等多种定义方式。此外,x86 平台上默认的 char 类型是一种有符号的类型,对应到鲲鹏上则是无符号类型,在移植过程中需要显示定义并将 char 类型定义为有符号,方法一是在源代码里加上 signed char,但是缺点是可能改不全从而引发一些不可预知的问题,方法二是直接用 fsigned-char 来修改,在不同架构下差异化的编译选项也可以通过 gcc 文档进行查询。
编译宏的移植:编译宏的作用就是让编译器知道编译哪些分支代码能够在不同架构下达到最优性能。如何对编译宏下面的代码实现移植?86 代码上有些编译器自带自定义宏,比如 smd 属性相关的宏在 x86 上是 SSE 开头的宏,对应到鲲鹏平台上就需要自定义它的编译宏和所相对应的分支。
Builtin 函数移植:Builtin 函数是编译器自带的函数,其在实际迁移项目中相当常见,主要是 crc32 校验值的计算。需要移植的普通 builtin 函数实际并不多,大部分需移植的 builtin 函数集中在 SSE intrinsic 函数内。
内联汇编函数的移植:第一种是指令替换,x86 上对应的是 bswap 指令,鲲鹏对应的是 rev 指令,其它有些操作和寄存器都是基于内联汇编的语法规则进行替换的。第二种是 Builtin 函数的替换,以 x86 的指令 popcnt 为例,比如 popcount 是对二进制数里面的 1 进行计数,对应到鯤鹏平台上所替换的是 popcountll。
SSE intrinsic 函数移植(SIMD 技术):Intel 的 SIMD 扩展指令统称 SSE,主要分为三类,MMX 是 64 位寄存器,SSE 到 SSE4 是 28 位的,三是 AVX256 和 AVX512。鯤鹏基于 SIMD 的技术发展比较成熟,现在有些基于开源量的 NEON 库主要是在图象处理和视频处理层面。
我们知道在实际的代码迁移过程当中,通常都是先编译,遇到问题之后再进行修改,再进行编译,循环整个过程,直到编译没有完成,完成迁移。但是这个过程比较麻烦,在前边编译的时候,不知道后面有多少问题。为此华为开发的 Porting Advisor 工具应运而生,针对 C/C++代码进行扫描分析,检查用户 C/C++代码中需移植修 改的 MakeFile 编译文件、X86 汇编及 SSE intrinsic 函数,并指导用户如何移植。
Porting Advisor 工具使用比较简单,主要分为三步,第一步是环境的部署,首先是 Porting Advisor 工具的安装,安装后准备需要迁移的源码;第二步通过 Porting Advisor 进行工程的分析扫描,主要是扫描其中的编译构建脚本、X86 汇编,包括 Intrisic 函数的识别等,最后会生成一个分析报告,给出需要移植的一些移植项,以及移植的修改建议。
解释型语言迁移
典型的如 Java、Python 语言,都属于解释型语言,Java/Python 编译好的程序是平台无关的字节码,由虚拟机解释执行,虚拟机完成平台差异的屏蔽。
首先看 Java 代码迁移,如下图所示,需要安装运行环境 JDK,Java 源码通过 Java 编译器之后就会生成一个 Java 的字节码,这时候可能 jar 包会有一些 SO 库的依赖,那就需要链接进行打包。
其中涉及的迁移改动点有三个:
1.安装 JDK 改动点:这里推荐成熟稳定的高版本 JDK,比如鲲鹏已经适配的 OpenJDK,可以直接通过 yum 安装使用。当然,客户可能还需要某个特定版本的 JDK,这时需要通过源码编译部署得到。过程如下:首先安装一个 GCC,其次获取 JDK 的源码,获取源码后配置编译选项,比如配置语言选项,然后设置目标平台的位数 64 位,忽略掉一些告警,最后调整 debuglevel。完成编译选项配置后,执行启动编译得到二进制文件,最后设置环境变量来进行验证,通过 Java version,可以看到当前得到的 Java 版本是否是想要得到的版本。
2.引用 SO 库的改动点:这里举一个例子,如下图所示。看到目录是包含 X86 的.SO 库,这时需要对 SO 库重新编译成 aarch64 的版本。迁移步骤如下:首先通过 Dependency Advisor 工具分析扫描 jar 包,识别出所依赖的 SO 库,然后下载 SO 库源码,安装 Maven、GCC 等编译环境,设置编译选项-fsigned-char,之后可以编译 aarch64 版本的 SO 库,替换掉 SO 库,最后重新打包 jar 文件。
3.程序运行时改动点:设置 JVM 参数,保证程序稳定快速的运行,这里总结三个经验和两个差异。经验一:完成一次 full GC 以后,应该释放 70%的堆空间。经验二:假设老年代存活对象大小是 X,那么建议堆的总大小是 X 的 3 到 4 倍,年轻代的大小是 X 的 1 到 1.5 倍,老年代的大小是 X 的 2 到 3 倍,永久代的大小是 X 的 1.2 到 1.5 倍。经验三:建议年轻代的大占整个堆空间大小的八分之三左右。差异 1:线程栈大小的 Xss 参数在 ARM 上默认值为 2M,在 X86 上为 1M,若 线程开的太多,需要使用 Xss 调整线程栈的大小,防止 OOM。差异 2:由于 ARM 和 X86 指 令集的差异性,导致 JDK 的 JIT 编译存在差异。可以通过设置参数 ReservedCodeCacheSize, 调整 CodeCache 大小。
再来看 Python 源码的迁移,其实与 Java 很类似,也是需要从编译环境和 SO 库两大方面入手修改。首先需要安装一个 Python 环境,进行 Python 源码的编辑,然后通过 Python 编译器把源码变成.pyc 自解码,如果代码里面调用含 C 代码模块或者纯 C 代码模块,需要把这部分代码编译成.SO,然后生成模块,最后将自解码和模块一块放到 Python 解释器进行运行。
其中涉及的迁移改动点有两个:
1.Python 版本改动:当前 Python2.X 版本,在 Python 官方已经不维护了,所以建议将 Python 环境升级到 Python3.X。过程如下:安装一个合适的 GCC 版本,配置编译选项-fsigend-char,随后在官方网站下载源码包,解压源码包,配置编译选项 conflgure 以及需要安装的路径。安装完成后会生成一个 make 文件进行编译安装,得到 Python3 的二进制文件。执行这个二进制文件查看是否是想要的版本,证明 Python 环境安装已经成功。
2.引用 SO 库的改动:不管是含 C 代码编写的模块还是纯 C 代码编写的模块,它的核心都是调用 SO 库,因此对于这样一个 SO 库需要重新编译替换成 aarch64 版本。步骤如下:首先通过 Porting Advisor 工具来分析源码,识别到依赖的 SO 库以及 C 代码,随后下载对应的模块源码,安装 GCC 编译环境,然后配置-fsigend-char 编译选项,执行模块中中的 setup.py 自动完成模块编译,今儿完成 aarch64 版本 SO 库的替换,编译的模块安装到 site-packages 目录下,供其他 Python 源码引用。
Maven 仓软件构建
Java 开发工具圈中,目前最主要的主流有 Lvy 依赖、Maven 依赖、Gardle 依赖三个开发工具,依赖管理已经成为了项目构建自动化工具中的一 个主要部分。Maven 是 Apache 下的一个纯 Java 开发的开源项目,基于项目对象模型(缩写:POM), 可以对 Java 项目进行构建、依赖管理。那么 Maven 如何做依赖管理?
在 Java 世界中,可以用 groupId、artifactId、version 组成的 Coordination(坐标)唯一标识一个依赖。 pom.xml 文件中一个典型的依赖引用如下图,Maven 编译时会自动拼接路径和文件名,去本地或远程仓查找。
Maven 软件仓库分为三大类。首先是本地仓库,本地仓库是默认存储在本地磁盘 默认在 ${user.home}/.m2 下;远程仓库一般使用国内镜像或者公司自己搭 建私服,可以加快 jar 包下载速度;中央仓库这是 Maven 团队维护的 Jar 包仓库。
而在使用时,首先会从本地仓库进行搜索,如果本地仓库有找到则直接反馈,如果本地仓库没有找到则去远程仓库进行搜索。远程仓库如果有找到,会把相关的组建下载到本地仓库,如果远程仓库没有找到,就会搜索中央仓库。如果在中央仓库找到所需要的组建,同样把灰这个组建下载到本地仓库,如果中央仓库也没有找到,则会在前台打印错误信息。
Maven 软件构建关键流程如下图所示:将 X86 依赖文件替换成 Kunpeng 依赖文件,重新构建,直到不包含 X86 依赖。
那么有没有一种软件仓全部包含鲲鹏平台的软件组建的呢?
这就引出了鲲鹏的 Maven 软件仓。Maven 仓部分 jar 包依赖 x86 so,无法在鲲鹏上直接使用,需要在鲲鹏上重新编译,部分 jar 包已编译好放在 鲲鹏 maven 仓内,可以直接使用。
为了配置优先搜索鲲鹏 Maven 仓,前面已了解 Maven 仓库搜索顺序,可以将鲲鹏 Maven 远程仓库放在首位,以便 Maven 优先下载 鲲鹏平台 jar 包。由于鲲鹏 Maven 仓只放了 arm 相 关 jar,所以 jar 包不全,可以配置第二个 Maven 远程仓库,当鲲鹏 Maven 仓搜索不到时,会自动搜索下一个 Maven 远程仓库。
因此,优化后的鲲鹏 Maven 软件构建关键流程如下图所示:可以直接从鲲鹏远程仓下载 ARM 依赖文件,无需重新编译依赖文件,这样的一个过程大大简化了工作量。
软件包迁移
常见的 Linux 发行版主要分为两类:类 RedHat 系列和类 Debian 系列。类 RedHat 系统中,软件包的格式是 rpm;类 Debian 系统中,软件包的格式是 deb。类 RedHat 系统提供了 rpm(全称是:RedHat Package Manager)命令来安装、卸载和升 级 rpm 软件包;类 Debian 系统提供了 dpkg 命令来安装、卸载、升级 deb 软件包。
而对于常见的应用程序,它包含的内容有二进制的文件、库文件、Jar 包还有一些配置文件、帮助文件。rpm 可以把应用程序打包,同时也包含以上的这些文件。所以将 X86 的 rpm 包重构到 Arm 的 rpm 包,需将 rpm 包含有 X86 的 so、二进制文件,替换成 arm 架构 so、二进制文件。
那么将 X86 rpm 包重构成鲲鹏 rpm 包流程主要分为四步:【扫描 - 编译 - 打包 - 验证 】
扫描:工具扫描 x86 rpm 识 别 x86 依赖文件。过程如下:首先下载 x86 rpm 软件包到 /opt/depadv/depadmin 目录下 (depadmin 为登陆用户名),之后用 Dependency Advisor 工具进行扫描。
编译:部分 jar 包已编译好放在鲲鹏 maven 仓,可以直接下载,减少重复劳动,对于 so,二进制文件或无法从 Maven 仓上找到 的 jar 文件,需在鲲鹏上重新编译。
打包:如下图所示,需要对文件进行打包,首先解压 X86rpm,将编译好的组件替换掉 RPM 包中对应文件,打包完成之后需要进行验证。
验证:验证分为两部分,首先是重新扫描,确认是否还有 x86 依赖文件,其次可以进行安装验证,验证它能否在鲲鹏平台正常运行。
需要强调的是,鲲鹏开发套件 Porting advisor,可以将以上步骤进行自动扫描,自动从鲲鹏 Maven 下载依赖文件,实现自动打包功能。
鲲鹏生态助力山城产业升级
硬件开放、软件开源、使能伙伴是华为构建鲲鹏生态始终坚持的信条。特别是在当前国际环境下国产化趋势不可逆,为智能时代而生的鲲鹏加昇腾多元化的计算架构相比其他国产化技术线路优势明显,打破英特尔世界垄断,让世界在计算上有第二种选择。
因此,为支持广大软件企业做好鲲鹏软件的迁移,鲲鹏计算产业生态重庆中心为开发者提供了四种服务:
免费的专家服务。鲲鹏重庆中心成立了一支由华为高级工程师组成的技术团队。可以免费为大家提供软件移植、业务迁移服务,也可以做联合解决方案创新。
免费的鲲鹏资源服务。满足开发者的软件适配迁移和应用的试点示范的业务需求,鲲鹏重庆中心提供了两种鲲鹏云,一种是标准的华为云服务及公有云服务,另外一种是本地鲲鹏云服务。
免费的人才培养考试卷,鲲鹏重庆中心将举办鲲鹏训练营、鲲鹏大赛、技术沙龙、鲲鹏专家培训,企业高校以及开发者都可以免费参加,同时鲲鹏重庆中心还会在高校开展鲲鹏课程、鲲鹏学院等。
现金激励。针对鲲鹏软件伙伴收入占比 TOP3 的主打软件产品的技术迁移和适配。基于鲲鹏昇腾开发创新的年度新产品,鲲鹏重庆中心将发放千亿现金激励和大量现金激励。
众人拾柴火焰高,在智能产业极速崛起并爆发出巨大需求和市场潜力的背景下,华为将始终携手产业合作伙伴一起构建鲲鹏计算产业生态,把数字世界带入每个人、每个家庭、每个组织,构建万物互联的智能世界。
评论