“我们非常希望 ARM 和鲲鹏的生态能成为下一个计算产业迭代的方向。”在 6 月 8 日于成都举办的华为 DevRun 开发者沙龙——四川鲲鹏开发者嘉年华上,华为鲲鹏计算产业开源与生态营销总监梁冰对计算产业未来展望道。
新基建风口下,算力一跃成为了新的生产力,云、AI 与 5G 则是新的生产工具,技术聚变将引发商业裂变,带动各行各业的数字化快速发展。基于 5G 等新兴技术的创新应用催生多样化算力的需求,市场既需要通用计算算力也需要异构计算算力。此外,摩尔定律的逐渐放缓,让算力和性能陷入一系列发展瓶颈,市场对创新架构的需求日益加深,计算平台的创新之战一触即发。
在此背景下,x86 架构的不足越发明显,功耗大、通用寄存器数量少、计算机硬件利用率低、寻址范围小等问题凸显,难以跟上算力发展的速度。与此同时,ARM 架构在移动互联网盛行的当下却开始焕发出别样的生命力。
“基于 ARM 架构来设计的鲲鹏,其成功的前提是早早地便看到了未来计算机算力架构的迭代之路。对华为来说,不光要在中国携手合作伙伴共建鲲鹏生态,为更多企业带来价值,更为重要的是要融入全球 ARM 的生态,共同推进 ARM 进阶为下一代计算机平台的事实标准。”梁冰对鲲鹏生态的意义阐述道。
从 x86 迁移到 ARM 架构的过程并不简单,本次活动中,华为鲲鹏计算专家对于鲲鹏软件迁移路径也进行了非常全面细致的讲解,同时针对软件迁移过程中可能遇到的问题及解决方案也进行了相关讲解,还为现场开发者设置了实操演练环节,一对一指导下进行鲲鹏软件迁移线上实验。
从 x86 向鲲鹏迁移的必要性众所周知,计算机是由软件和硬件组成的,上层的软件是通过指令集驱动下层的硬件,软件想要跑在 CPU 上的话,那它必须要有对应的指令集。
如上图所示,整个计算机的计算基础架构,从底层的晶体管、物理原材料,二极管也就是逻辑门电路,到往上走的微架构、自评级架构,再往上面走就到了操作系统所完成的二进制机器译码汇编高级语言、JavaC 等等,整个技术站从复杂到抽象,技术语言也从经历一个简单的交换指令发展为汇编进行访存和锁存,再到形成机器码,这个过程中最核心的变化在指令集上。
想要成功运行,底层计算平台就必须能够支持该 CPU 的指令才可以,这也是在 x86 和鲲鹏编译的不同之处。
如上图所示,x86 和鲲鹏使用的指令是不一样的,简单来讲,在鲲鹏上使用的是精简指令集,而在 x86 上使用的是一个复杂的指令集。综合来讲,它有三点主要的差异:
架构差异:x86 和鲲鹏处理器 (aarch64) 属于不同的架构。
指令集差异:x86-- 复杂指令集,鲲鹏处理器 -- 精简指令集。
向量寄存器差异:x86 和鲲鹏处理器使用向量寄存器不同,向量指令集也存在差异。
从这三点出发,一个在 x86 上运行的程序根本不可能毫无阻碍地就可以在鲲鹏上使用,必须经过编译,同时也证明了迁移的必要性。
迁移的五个步骤1. 迁移准备:信息收集 & 环境申请
信息的收集主要分为两部分,首先是硬件信息的收集,主要就是一些型号,目的是根据此类信息匹配一个 x86 的服务器;其次是收集软件栈信息,包括操作系统、虚拟机、中间件、编译器、上层依赖的开源软件、商业软件、业务软件等信息。 2. 迁移分析:软件栈分析 & 编程语言分析
这一过程要做的就是对收集到的信息和软件栈做初步分析,目的是判断是否真正需要迁移,评估迁移的工作量。
对开源软件来说,因为社区发展已经比较成熟,迁移相对较为简单,通过基于鲲鹏的架构分支或者鲲鹏支持的软件包,自行安装即可。对于自研软件来讲,情况则较为复杂,如 C、C++ 这类编译型软件,从指令集差异化出发,需要重新编译后才能完成迁移,而 Java、Python 这种解释型的语言,因为其虚拟机如 JDK、PVM 已经把上层的一些跟指令集相关的东西屏蔽掉了,平滑地迁移过去即可。对于商用软件而言,不会公开源码,如果需要迁移,就必须要联系厂家去编译一个鲲鹏的版本,并且完成一系列的适配。
此外像运行环境、虚拟机、编译器和操作系统这些也是要进行替换,但是这些并非需要重新编译,因为在华为云鯤鹏论坛内有软件仓库,可以直接去软件仓库下载由鲲鹏官方所做的经过验证的版本。 3. 编译迁移:代码迁移 & 软件包迁移
编译型的语言,之所以迁移起来比较困难,原因就在于涉及到比较多的迁移点,下面将从代码和软件包两方面进行阐述。
对于对指令集有依赖的代码来说,与 x86 架构相关的,都需要替换成 ARM 架构下的语言;像以 Java、Python 为代表的解释型语言,换一下 JDK 和 PVM 就行了,如果语言中调用了编译型语言,必须把这部分重新编译才可行。对于软件包来说,其迁移与 Java、Python 语言类似,即扫描出来里边的对编译型语言的依赖,把这一部分依赖进行替换即可。 4. 性能调优:性能指标测试 & 性能优化
经过前面几个步骤之后,软件迁移其实就基本完成了,之后要对性能进行调优,主要分为建立基准 、压力测试 、确定瓶颈、 实施优化、 确认效果五个步骤。
首先需要建立调优基准,该基准根据当前的硬件配置、组网、测试模型来做综合评估,以建立合理的条有目标;其次在调优目标建立后,通过压测工具对软件或系统进行加压,在加压过程中暴露性能瓶颈,确定瓶颈之后对瓶颈进行优化;第四,注意在优化过程中要及时记录,因为优化并不一定是正向的,出现负向优化时需要及时回退;最后在优化措施实施完成后,需要重新启动压力测试工具以确认优化效果。 5. 测试与认证:压力测试 & 长稳测试 & 规模商用
调优结束之后,接下来就要把功能运力、长稳运力以及性能运力都跑一遍,达到一个商用的标准,就可以筹备上线了。此外也可以将软件和系统进行鲲鹏展翅认证,其可以扩展应用的软件使用空间并能够加入鲲鹏生态。
不同语言的迁移注意事项实际上,像 Java、Python、Perl 这种跨平台的开发语言,它的迁移的技术难度相对来说是比较低的,主要是因为 Java 有一个 JBM,Python 中存在一个解释器,它们屏蔽了大部分的平台架构上的差异。与之相反,C 和 C++ 的难度相对来说要高一些,原因是如内敛函数还有 x86 加速的一些指令,无法支持像微软这种闭源的开发架构。
典型的如 C/C++/Go 语言,都属于编译型语言。编译型语言开发的程序在从 x86 处理器迁移到鲲鹏处理器时,必须经过重新编译才能运行。如下图所示,源码需要由编译器、汇编器翻译成机器指令,再通过链接器链接库函数才能生成机器语言程序。
接下来就是 C/C++ 代码的编译构建了,这个过程一共分为六步:
获取源码:通过 github 或第三方开源社区获取
准备编译环境:安装编译器 gcc 等
使用源码中的 CMakeLists.txt 或 configure 脚本生成 makefile
执行 makefile 编译可执行程序
替换依赖库:重编译或替换依赖 x86 平台的 so 库
将可执行程序安装部署到生产或测试系统
既然是最为复杂的,C/C++ 语言的迁移问题也是涉猎最广泛的,主要涉及到七类问题:
编译脚本和编译选项的移植:以 x86 下 -m64 代码为例,其主要功能是将应用程序编译为 64 位,对应到鲲鹏上是用 -mabi=lp64 的编译选项,此类编译选项需要在脚本中修改;此外, x86 平台上默认的 char 类型是一种有符号的类型,对应到鲲鹏上则是无符号类型,在移植过程中需要显示定义并将 char 类型定义为有符号,方法一是在源代码里加上 signed char,方法二是直接用 fsigned-char 来修改。
编译宏的移植:编译宏的作用就是让编译器知道编译哪些分支代码能够在不同架构下达到最优性能。如何对编译宏下面的代码实现移植?86 代码上有些编译器自带自定义宏,比如 smd 属性相关的宏在 x86 上是 SSE 开头的宏,对应到鲲鹏平台上就需要自定义它的编译宏和所相对应的分支。