小支同学华为鲲鹏微认证——鲲鹏软件迁移实践、鲲鹏软件性能调优实践

“北冥有鱼,其名为鲲。鲲之大,不知其几千里也。化而为鸟,其名为鹏。鹏之背,不知其几千里也;怒而飞,其翼若垂天之云。”
摘要:鲲鹏开发套件 Kunpeng DevKit 可实现两人天快速完成代码迁移,提供全栈开发工具,集代码迁移、编译调试、性能调优、异常诊断等工具和功能于一体。

一、鲲鹏之志
1.1 鲲鹏平台
鲲鹏平台,为全世界的开发者提供了一种新的算力选择。从硬件的开放,到系统软件的开源,涵盖从底层硬件、基础软件到上层行业应用的全产业链条,在国计民生的各个行业取得了重大效果或者进展。工欲善其事必先利其器,鲲鹏开发套件 Kunpeng DevKit 是华为公司为了广大鲲鹏开发者打造的一把屠龙之刃,帮助开发者高效开发,一键迁移。

1.2 Kunpeng DevKit
鲲鹏开发套件 Kunpeng DevKit 提供全栈开发工具,集代码迁移、编译调试、性能调优、异常诊断等工具和功能于一体。将开发者的工作各个环节一一串联,提供了一个方便、快捷和专业的工具包,通过鲲鹏 DevKit 可以帮助用户高效开发,一展宏图。

真正的武林高手,内功很强,外功同样很强!DevKit 产品设计和用户体验同样优秀!
时间有限,本文着重分享汇编翻译技术和 Kunpeng DevKit 产品体验。
二、汇编自动翻译
2.1 汇编代码
众所周知,汇编语言历史悠久,上手难度较高,是任何一种计算机或其他可编程器件的低级语言。在不同的设备中,汇编语言对应着不同的机器语言指令集。


一种汇编语言专用于某种计算机系统结构,如 x86_64 或 aarch64 汇编。这意味着在某种程度上汇编语言可以真正的操控硬件,可以完成高级语言不能完成的任务。同样,正因为汇编语言接近硬件平台,所以汇编语言也是晦涩难懂、难以上手。
2.2 汇编样式
每一个计算机平台都对应着自己的计算机平台,内存、寄存器等语法格式错综复杂。


汇编语言使用方式也多样,单指令简单嵌入汇编、多指令简单嵌入汇编、全汇编文件。这相当于在我们现代社会讲古文古诗,全篇都使用文言文或者其中引用两句古诗词。


2.3 意义和挑战
将代码从一个平台迁移到另一个平台,如果其中需要牵涉到汇编语言翻译,其代码迁移难度巨大。

目标是两人天完成应用迁移,然而如果代码中包含汇编语言,有可能 12 人都无法完成迁移。不行,不可以!华为必须开发汇编迁移工具!
“代码千万行,汇编就几行,迁移没工具,开发泪两行”
2.4 使用场景
在使用汇编语言时,嵌入汇编的指令数大部分是小于三条指令,使用都较简单,指令也比较集中。


全汇编文件中 SIMD 指令占了绝大多数,指令相对集中。


可以发现,常用汇编指令和 SIMD 指令占了汇编语言大半江山。只要能够解决常用指令和 SIMD 指令,项目就成功了一大半。

2.5 总体思路
目标是识别所有 X86 汇编,自动翻译(大多数场景且性能尽量不衰减)。
在开始时,对于常用的指令进行翻译,而后随着用户规模的扩大和使用量的增加,根据用户需求,逐步加入用户所需要的指令。
第一个技术点:自动化
第二个技术点:技术复用
整体技术架构面向未来,拥有生命力。所有就有了下列设计原则
设计原则
使用便利 - 一键迁移
可扩展性 - 翻译范围
可维护性 - 源码翻译
架构重用 - 不同场景
技术复用 - 不造轮子

2.6 总体设计
W + 二
“二”,直接翻译,实现从 X86-64 → AArch64
“W”,庖丁解牛,虽然操作较为复杂,但是利用编译技术的现有能力,加以改造为翻译所用,实现翻译效率最优化。依据上文所述汇编复杂特性以及平台便捷化目标,产生以下设计原则和设计方案
设计原则
汇编样式复杂
平台间差异大
目标要求很高
设计方案
能用则用
需改尽改
当快则快
曲折前行

三、汇编自动翻译部分技术
3.1 嵌入汇编的识别
对于全汇编,识别方式较为简单,通过文件的后缀即可识别汇编文件,问题在于嵌入汇编的识别。我们使用 Clang-Tidy 编译技术实现该目标。
Clang-Tidy:基于 LLVM 的静态语法检查框架,提供语法(AST)解析能力。
基于 Clang-Tidy 工具集拓展汇编识别和替换规则,使得 AST 关键节点暴露。定位汇编代码后即可为所欲为,进行翻译处理。
识别流程图如下:

下面给出一个小案例:


3.2 简单嵌入汇编的自动翻译
基于规则的自动翻译,即通过某种特征匹配规则识别和转换相应的代码。
1.指令操作数映射
2.汇编语句特征分析(绑定步骤 1)
3.规则库规则匹配(绑定步骤 2)
4.根据规则进行代码翻译

首先对汇编语句进行语法解析,解析完以后可以得到各个特征,再在规则库中进行特征规则匹配,即与语法结构进行匹配,在规则进行转换时,相对应的语法结构也进行转换,两者合一,即代码翻译完成。

3.3 复杂汇编的自动翻译
对于复杂汇编,指令条数多,语法结构复杂,千变万化,也可能存在外部引用等问题。
1.指令组合无法穷举
2.汇编模块引用外部变量
3.消除平台间调用差异
4.SIMD 指令对等翻译

上文中“W + 二”设计结构在复杂汇编翻译中发挥重要作用。下“一”进行 SIMD 直接翻译。

3.4 汇编翻译举例
将 X86-64 一键翻译为 AArch64,并且提供两种方案,旧的路径依旧可以在 X86 上执行,没有任何问题,并且创建的新分支可以运行在 Kunpeng 平台上。生成代码后,可以一键替换掉旧代码。提供一个 main 函数,可以看作一个驱动,测试驱动可以在 X86 和 Kunpeng 平台同时运行。运行结果一致。保留 X86 平台的兼容性,代码在不同的平台运行可以保持 100%的兼容和正确。
简单汇编翻译:

复杂汇编翻译:

天啦,这也太快了。朋友们,赶紧下载使用吧,一键翻译,迁移你的应用至鲲鹏平台。冲起来!
四、体验设计
Kunpeng DevKit 功能强大,使用优雅。采用超级方便的一站式解决方案,帮助开发者加速软件开发、迁移和算力升级。一站式开发套件、全流程效率提升。一站式迁移、编译、测试、分析。

4.1 应用迁移体验设计
开发者依照个人经验和习惯可以大致分为三类:
经验较少的用户,重度依赖自动化,希望全自动化迁移
有一定经验,合理依赖自动化,希望自己主要迁移过程
经验丰富,浅度依赖自动化,自己纯手工迁移

鲲鹏 DevKit 针对上述三种不同类型的用户,做了大量产品体验层的设计。
第一类开发者,通过系统全面自动化能力,做到无感知迁移。提供动态二进制翻译工具,自动的将 X86 平台指令集翻译成 Kunpeng 平台指令集。整个过程透明、全自动,无需额外工作,整个应用即可应用在 Kunpeng 平台上。

第二类开发者,希望参与整个应用迁移的过程和环节中,了解翻译过程。鲲鹏 DevKit 自动识别问题、提供建议辅助决策、提供替换代码─键修改,极简体验。

第三类开发者,可能存在开发者认为自动化重构是一个黑盒子,不可信任,在这方面,困 DevKit 提供了透明展示等内容,使得用户相信,该工具是安全的。

4.2 性能调优体验设计
设计架构时,将人的思想行为融入其中,使得工具的使用更加自然化、更加符合人类认知的思考,从整体到局部,从宏观到微观。

4.3 小例子
举几个小例子可以说明上述体验设计,一个是硬件调优 3D 可视化,基于认知模型、表现模型极简抽象,从物理世界到虚拟世界的映射。

第二个例子是性能分析时,进程/线程拥塞的直观可视化。

在系统设计时,运行大量的信息可视化表达,一目了然,清晰可见,优雅体验。

五、总结
无需多言,一图流概括!

鲲鹏 DevKit 产品从设计到功能都是极好的,可以发现为了鲲鹏的发展和壮大,华为在此花了很多心思,希望各位开发者朋友们多多尝试,或许鲲鹏比你我想象的更加强大、友好、便利。
鲲鹏软件迁移概述
由于指令集上的差异,在 x86 平台上编译生成的应用程序,在鲲鹏处理器平台运行时,需要进行重新编译。

1. 鲲鹏软件迁移的五个步骤
迁移准备
主要做一些信息收集,以及编译环境的准备。收集包括操作系统、中间件、业务软件等信息后,还要做编译环境准备。

迁移分析主要指的是,对搜集到的软件栈信息打开进行详细分析,包括使用什么语言,是否有相应的 X86 依赖需要移植。
第一类是业务软件的展开分析,包括开源软件、自研软件和商用软件。
其中,开源软件可通过获取开源代码,进行重新编译,或获取对应的 ARM 包,获取源码重新编译。
自研软件根据语言可分为编译型语言和解释型语言开发的自营软件。
在商用软件领域,我们可以获取支持鲲鹏处理器的一个商用软件版本,当我们没法获取相应的商用软件版本时,可以通过其它软件或者开源软件来进行替换。
第二类是对软件的运行环境进行分析,运行环境可分为 JDK 以及编译器还有操作系统。JDK 替换可以替换成我们支持的华为 JDK,如 openJDK;编译器就是根据我们使用系统自带的一些编译器或者迁移时源码会规定一些 GCC 的版本,这时候我们更推荐的是使用 GCC7.3。操作系统可以通过兼容性助手,查询鲲鹏处理器支持的操作系统版本。

测试的话会经过功能测试、性能测试、长稳测试,这些测试的最终目的都是为了保证规模的商用。这个其实还有一个就是鲲鹏展翅论证。在认证上面,截止 6 月 5 日,累计有 809 家行业伙伴获得鲲鹏展翅论证。
2.典型案例
这里我们拿华为内部项目举例。这个项目涉及的迁移软件代码比较多,代码的规模大概在 450 万行左右,其中 C、C++代码占了一大半,有 272 万行,还有 165 万的 Java 代码,还涉及到 140 多个依赖库。在迁移 C、C++代码和依赖库的过程中,其实我们前面讲到的一些包括汇编指令迁移、选项修改、数据流行修改,其实这些都涉及到了,最后我们还做了代码的归一,构建脚本的归一,目的是兼容鲲鹏处理器平台和其它处理器平台,让代码能在多个平台运行。经过编译和移植后,最后还进行了系列性能调优,最后测试结果是:与 X86 持平。
3.华为鲲鹏开发套件
华为开发了一系列套件,帮助完成分析、迁移、调优过程。在迁移分析阶段,推出分析扫描工具,帮助我们扫描代码依赖的依赖库,做代码初步评估;在性能调优阶段,我们推出性能优化工具,它能做全景资源监控,针对可能出现的热点函数进行监控。
第一类迁移问题:编译脚本、编译选项移植;

一个例子是,定义编译生成程序为 64 位,这时候在 X86 下面编译选项是-M64,在我们鲲鹏处理器平台下,我们需要通过-Mabi,等于 LP64 这个编译选项进行替换。
第二类迁移问题:编译宏移植
什么是编译宏?一段好的代码,比如很多开源工程,一个工程代码会写不同的分支,每个分支对应不同的架构平台,在我们编译器去编译和运行过程中,怎么知道执行哪个分支?这就是编译宏在起作用。它类似于一个标签,告诉你在当前平台下,你需要去执行这个分支下面的一个代码。
编译宏的移植,第一类是 gcc 编译器自定义的宏;第二类是用户自定义的宏。
第三类迁移问题:builtin 函数移植
builtin 函数,是我们编译器自定义的功能函数,这些功能函数通常功能较简单,但内部实践进行了优化,具有较好的性能,大家使用过程中如果有相应的需求可以进行使用。

第四类迁移问题:内联汇编函数移植
内联汇编的迁移主要有两种方法:第一种方法是一个汇编指令方式的替换来进行一个移植。第二种方式就是通过 Buding 函数的方式进行替换。

第五类迁移问题:SSE intrinsic 函数移植
什么是 SIMD?英文全称是 Single Instruction Multi Data,指通过单条指令处理多数据流的并行处理技术,能在批量数据操作时进行向量化运算加速,具有较高的执行效率,在多媒体处理、矩阵运算等场景都有广泛的应用。
关于 SIMD 里的 MMX 和 SSE 指令迁移,鲲鹏处理器采用精简指令集,使用 128 位寄存器实现 SIMD(Single Instruction Multi Data)计算。在实现本例 16 个浮点数的相加时,使用两条 vaddq_f32 指令分别完成,每条指令完成两组共 8 个浮点数计算,最后再从向量寄存器中分别取出 8 个浮点数累加。
SSE intrinsic 函数主要有两个移植方法,第一个方法是:基于 avx2neon.h、SSE2NEON.h 开源文件移植;第二个方法是:手动替换移植。

JAVA、Python 代码迁移
1.Java 代码迁移
Java 运行过程中可能涉及的迁移改动点

Java 源码移植过程是这样的,首先安装 JDK,将 Java 源码通过 Java 编译器编译;其次,对被调用的 SO 库,我们需要替换成 aarch6464 版本;再次,在程序运营时,可能涉及到一些参数的修改。
针对迁移改动点的处理方法
安装合适的 JDK 版本,需要通过源码编译、部署得到。

包含 SO 库调用的 jar 包迁移方法,首先通过 Dependency Advisor 工具分析扫描 jar 包,识别出所依赖的 SO 库,然后下载 SO 库源码,随后安装编译环境比如说 Maven、GCC,然后设置编译选项-fsigned-char,之后可以编译 aarch64 版本的 SO 库,然后替换掉 SO 库,重新打包的 jar 包,这样得到的 jar 包是可以在鲲鹏平台上运行的。
最后一个迁移改动点。需要我们设置 JVM 参数,保证程序稳定快速的运行。

2.Python 代码迁移
Python 代码迁移改动点有哪些?首先是我们的 Python 版本,建议客户将 Python 环境升级到 Python3.X;其次,在含 C 模块或者全 C 模块的迁移上,可以通过 Porting Advisor 工具分析我们的源码,然后识别到依赖的 SO 库以及 C 代码,随后我们下载对应的研源码模块,安装 GCC 编译环境,配置-fsigend-char 编译选项,执行模块中的 setup.py 这个文件自动完成模块编译。编译完成后,自动绘完成 aarch64 版本库的替换,再将编译完成得到的模块安装到 site-package 的目录下,供其他的 Python 源码调用。
如何通过 x86 架构的 rpm 包重构得到鲲鹏平台
将 x86 rpm 包重构成鲲鹏 rpm 包,在流程上,分为四个阶段,首先扫描识别对 x86 依赖的文件。第二阶段,是编译阶段。如果是 jar 依赖文件,需要从鲲鹏 Maven 仓上查找,或者鲲鹏上重新编译;如果是 so 或其它二进制依赖文件,需要在鲲鹏上重新编译。第三阶段,是打包,主要步骤是,解压 x86 rpm 并将 x86 依赖文件替换成阶段二鲲鹏 Maven 仓查找到的文件或鲲鹏上重新编译的文件。第四阶段是验证,主要通过扫描来验证,是否还有 x86 依赖文件。
技术原理
在这一部分,我将介绍迁移的技术原理,以及如何利用现有的 Java 代码进行迁移。以下是整体迁移的流程图与关键代码示例。
架构解析
对鲲鹏架构的解析是理解源码迁移的关键。我绘制了架构图,并用一些文字补充其中的细节。

鲲鹏平台采用 ARM 架构,适合高性能的数据处理。
与 Java 应用的交互主要通过 RESTful API 进行。
数据库的读写均经过优化,以适应新架构的特点。

编辑源码分析
在进行源码迁移时,深入源码的调用流程至关重要。下面是我整理出的调用流程图和部分源码细节。

应用场景
鲲鹏的迁移不仅仅是技术上的挑战,也为许多业务场景提供了新的机遇。我绘制了一份旅行图来描述这一过程。

编辑在外部服务的调用中,我们强调了通过 API 适配层与旧系统进行解耦。
扩展讨论
在深入讨论鲲鹏源码迁移的潜能时,可以借助思维导图和数学公式帮助理解。

参考案例:华为鲲鹏 DevKit 训练营
基于华为云弹性云服务器 ECS(搭载 openEuler 的鲲鹏通用计算增强型)完成鲲鹏代码迁移工具实践
【摘要】 基于华为云弹性云服务器 ESC(鲲鹏服务器),部署鲲鹏代码迁移工具利用扫描迁移工具进行源码分析,根据扫描建议修改源码,让源码在鲲鹏平台可以正常编译运行


更多详情可参考鲲鹏开发者社区。
一、目标
基于华为云弹性云服务器 ECS,自行部署鲲鹏代码迁移工具,完成鲲鹏代码迁移工具实践——进行 Megahit 源码迁移。利用扫描迁移工具进行源码分析,根据扫描建议修改源码,让源码在鲲鹏平台可以正常编译运行。
华为云弹性云服务器 ECS 配置:

二、操作前提
1. 认真观看迁移工具的实战视频
可到鲲鹏开发者社区查看,还有很多详细的文档资料啊。
2. (可选)申请远程实验室
因为 ECS 需要购买,如果不方便购买,可以到在鲲鹏社区申请免费的远程实验室,操作系统选择 OpenEuler。
不得不说,远程实验室的配置还是很强大的啊。

申请之后,会收到一封邮件,邮件提供了账号等信息,注意要按照邮件指导,在 VPN 端登录,之后才能使用远程实验室。
注意,请卸载除官方提供的 VPN 软件外的其他 VPN 软件,否则可能即使 VPN 登录成功,也无法访问,切记!!!这是血泪教训。
下面操作对 ECS 和远程实验室的操作都做了介绍,无论选择哪种方式,都可以的!
三、准备工作
如果你使用的是远程实验室,按照官方介绍,是打开工具的 web 网页 ,并进行登录。该 web 界面的 IP 地址,账号以及密码等信息在邮件中有详细说明哦。注意如果提示风险,要选择继续哦。

登录后的界面为:

好了,就是先看看哈,验证下可以正常访问远程实验室,后面会用到,这里我们先来做准备工作,用 MobaXterm 登录刚购买的 ECS 啊。
下面准备 Megahit 源码。这里简单介绍下哈,Megahit 是一个超快速和内存高效的 NGS 汇编程序。它是针对多基因组优化的,但也适用于一般的单基因组组装和单细胞组装。需要注意的是 Megahit 源码包存在大量汇编,后面我们会注意到迁移到鲲鹏平台前需要识别并验证通过“鲲鹏代码迁移工具”迁移后的代码是否正确,以及识别出是否还有“鲲鹏代码迁移工具”遗漏的相关文件。
1. 使用 MobaXterm 工具,以 root 用户登录服务器。
就是 ssh 登录,常规操作了,如果看到类似如下界面,说明登录成功:

2. 进入“鲲鹏代码迁移工具”源码文件存放路径。

3. 下载 Megahit 源码。

4. 将代码进行合并。
注意如下代码不对,正确代码请见这小项最后。
这里注意不要直接复制教程中所给的代码,因为教程中的-init
中的-
符号有问题,会报错如下:

或者

其实-init
中的-
符号应该是英文下的才对,也可以看到修改后-init
变为了蓝色,MobaXterm 就是强。

但看提示好像还是不太对啊,仔细看会发现打印信息给了提示,应该是--init
。

应该是正确运行了,结果如图,没什么打印信息:

5. 创建构建文件夹并进入。
6. 生成 Makefile 文件。
注意,这里运行可能报错,如下:

这可能是没有设置cmake
路径或者没安装camke
,我们使用如下命令,来看看:

那来安装一下吧,不管有没有了,马上行动起来。这里我安装的是cmake 3.15
,不是最新版哈,下面来介绍下安装,来嘞。
获取源码,并解压

编译安装

运行中的截图(这个过程有点长,大家可以先休息一下哈):

运行完成截图:

接下来执行命令:

运行完成截图:

那么接下来执行命令:

下面检查是否正确安装,执行如下命令:
如果看到如下界面,表示成功了:

好了,接下来可以执行之前的命令了:
得到运行结果:

7. 修改 megahit 目录属组。

四、源码迁移
下面是重头戏了哈,使用鲲鹏代码迁移工具进行代码迁移,就是用我们之前打开的 Web 界面,赶紧来试试吧。
注意,Web 界面长时间不操作会自动退

编辑
出登录,需要重新登录
注意,论坛发帖,编辑帖子时间一长,也会显示保存问题,大家记得及时保存,最好,写一些就发布,之后再编辑,再发布,以免丢了内容(虽然有草稿箱),这都是血泪教学啊,切记!!!
1. 源码分析参数填充

上述参数说明:
源码文件存放路径:
选择源码包 megahit/build,就是之前我们可下载了megahit
,这个很有意思,点击一下源码文件存放路径的方框,就会弹出一个下滑栏,选择我们的路径即可:

目标操作系统:
openEuler 20.03
这点没问题,这个在申请远程实验室的时候,我们就说了要选这个系统。
编译器版本:
GCC 7,3
这里要说明下,作业帖给的是BiSheng Compiler 2.1.0
,应该是毕昇编译器,但没这个选项,那我们就看看具体版本吧,在 MobaXterm 执行命令:
可以看到:

嗯,是GCC 7,3
无疑了。
注意执行如下命令亦可:

好了,全选好了,就执行开始分析吧!

这是运行中界面:

这是运行完成的界面:

2. 任务执行成功,查看源码报告。
点击上图中右上角的报告即可查看,可跳转到如图界面:

3. 点击报告源码迁移建议,查看需要迁移的文件。
注意,我这里提示让跳转到最新报告查看,跳转即可,因为之前我运行了一次,如果你是第一次运行,不会有此问题哈。

我们应该依次单击上襦左侧文件列表,查看需要迁移的文件。
根据系统提示的修改建议进行修改,鼠标点击内嵌汇编代码(cpu_dispatch.h), 可以看到四处待修改点。如图所示的红色波浪线展示的部分。
注意,我们将光标悬停在待修改代码出,就会弹出修改建议了

当然,我们能根据给出的建议手动修改,但是还有更便捷的自动修改哦,更快,不过注意自动修改后检查一下。自动修改很简单,在之前光标悬停的基础上,选择Quick Fix
,如图所示:

之后在如下图所示的两个选项中任选一个即可。

来看看效果:
这是第一处的修改后:

这是第二处的修改后:

这是第三处的修改后:

我们仔细看看这些长段的绿色注释部分,可以看到自动修改已经给出了具体建议。两处修改点所给的建议应该还是准确,直接去掉注释,效果如下:


最后,千万别忘了点击 保存。要知道,人生悲哀莫过于编辑的文件没有保存啊。

你以为这就结束了?当然没有,接着来吧!
根据系统提示进行修改,鼠标移至构建文件(megahit_core.dir/flags.make)待修改点处,可以看到两处待修改点。

这建议很中肯啊,应该是提示 Kunpeng platform 不支持BMI2
和POPCNT
指令,手动修改代码,删除指令-mbmi2
和-mpopcnt
指令。
这还没完,别忘了,还有一处呢!
鼠标移至构建文件(megahit_core_popcnt.dir/flags.make)待修改点处,可以看到一处待修改点。

根据建议提示 Kunpeng platform 不支持POPCNT
指令,手动修改代码,删除指令-mpopcnt
指令。删除后,红波浪线马上就消失了哈。

还是那句话,千万别忘了点击 保存。
五、迁移后重新编译
这里就又回到 MobaXterm 了。
1. 添加KunpengTrans.h
头文件
将KunpengTrans.h
头文件添加到目录/opt/poradv/portadmin/sourcecode/megahit/src/utils。执行如下拷贝命令:

2. 再次执行 make 命令。
在 ECS 上需要执行命令:
见证奇迹的时候到了!

尴尬,报错了,赶紧看看!

显示没有该文件,但这个文件<x86intrin.h>
是x86
相关的,应该是x86
平台的系统头文件,而我们用的是鲲鹏处理器,基于ARM
的,本来就没有这个文件哈。下面,执行vi
命令进入文本,注释 11 行代码:
对了,在英文模式下,单击键盘上的字母I
就能编辑了。

退出保存,需要先点击键盘左上角的Esc
键,之后执行:
再次执行 make 命令,编译通过。
注意,编译是比较耗费时间的,大家可以先休息一下,眺望远方,放松下眼睛。编译运行中界面:

top
命令查看 CPU 运行情况:

经过大约 2 分钟的等待,编译完成了,期间运行内存在 3.5GB 上下浮动。完成界面如下图所示:

六、运行和验证
记住啊,目前我们是使用 MobaXterm 工具,以 root 用户登录远程实验室的服务器。
1. 下面,进入可执行文件的安装目录。其实,就是当前目录,因为我们之前就是在这个目录编译的,这里是为了再确认一下。
2. 执行以下命令运行:
注意:make simple_test 里用到的.fa 文件是 github 上下载软件包的时候就自带了,无需额外下载。
运行截图:

最终运行结果展示:

搞定了,完结,撒花!!!

评论