2025上半年,最新 AI实践都在这!20+ 应用案例,任听一场议题就值回票价 了解详情
写点什么

TaiShan 服务器代码移植经验分享

王博

  • 2019-09-29
  • 本文字数:3712 字

    阅读完需:约 12 分钟

TaiShan服务器代码移植经验分享

经历过 2 个项目的业务代码从 X86 服务器迁移到 aarch64 泰山服务器上,以前没有相关经验摸索了好久,踩了很多坑,现在迁移工作也差不多收尾了,Taishan 服务器上跑比 X86 的溜多了。写了一篇代码迁移经验总结,欢迎大家参考。

编程语言简介

按照翻译方式的不同,高级语言通常可以分为两类:一类是编译翻译,一类是解释翻译,分别对应着编译型语言和解释型语言。

1.编译型语言

典型的如 C、C++语言,都属于编译型语言,源代码到执行的过程概括如图 1-1 所示。C/C++编译好的程序是机器指令,由操作系统加载到存储器(一般为内存)后由 CPU 直接执行。



图 编译型语言执行过程


基于编译型语言开发的应用程序,例如 C/C++语言应用程序,其编译后得到可执行程序,可执行程序执行时依赖的指令是 CPU 架构相关的。因此,基于 x86 架构编译的 C/C++语言应用程序,无法直接在 TaiShan 服务器运行,需要进行移植编译,移植编译过程中遇到的问题可以参考第 2、3 章提供的方法解决。

2.解释型语言

典型的如 Java、Python 语言,都属于解释型语言,源代码到执行的过程概括如图 1-2 所示。Java/Python 编译好的程序是平台无关的字节码,由虚拟机解释执行,虚拟机完成平台差异的屏蔽。



图 解释型语言执行过程


基于解释型语言开发的应用程序,是 CPU 架构不相关的,例如 Java、Python,将这类应用程序移植到 TaiShan 服务器,无需修改和重新编译,按照与 x86 一致的方式部署和运行应用程序即可。Java 应用程序 jar 包内,可能包含基于 C/C++语言开发的 so 库文件,这类 so 库需要移植编译,移植编译 so 库遇到的问题可以参考第 2、3 章提供的方法解决,使用编译得到的 so 库重新打包 jar 包。

准备工作

C/C++程序移植需要安装编译器,推荐使用 gcc7.3 及以上版本(最低不低于 4.8.5),下载安装参考链接:


gcc7.3版本下载地址


安装步骤参考

移植相关问题处理-编译脚本移植类问题

1.1 -m64 编译选项

现象描述


告警信息:gcc:error: unrecognized command line option ‘-m64’


可能原因


-m64 是 x86 64 位应用编译选项,m64 选项设置 int 为 32bits 及 long、指针为 64 bits,为 AMD 的 x86 64 架构生成代码。在 ARM64 平台无法支持。


处理步骤


将 ARM64 平台对应的编译选项设置为-mabi=lp64。

1.2 char 数据类型的符号

现象描述


告警信息:warning:comparison is always false due to limitedrange of data type


可能原因


char 变量在不同 CPU 架构下默认符号不一致,在 x86 架构下为 signed char,在 ARM64 平台为 unsigned char,移植时需要指定 char 变量为 signed char。


处理步骤


在编译选项中加入“-fsigned-char”选项,指定 ARM64 平台下的 char 为有符号数。

源码修改类问题

2.1 代码中汇编指令需要重写

现象描述


ARM 的汇编语言与 x86 完全不同,需要重写,涉及使用嵌入汇编的代码,都需要针对 ARM 进行配套修改。


处理步骤


需要重新实现汇编代码段。


示例:


在 x86 架构下:



在 ARM64 平台下,使用 gcc 内置函数实现:


2.2 替换 x86 CRC32 汇编指令

现象描述


编译错误:unknownmnemonic crc32q' --crc32q (x3),x2’或 operand 1 should be an integer register – `crc32b (x1),x0’


或 unrecognizedcommand line option ‘-msse4.2’。


可能原因


x86 使用的是 crc32b 和 crc32q 汇编指令完成 CRC32C 校验值计算功能,而 ARM64 平台使用 crc32cb、crc32ch、crc32cw、crc32cx 4 个汇编指令完成 CRC32C 校验值计算功能。


处理步骤


请使用 crc32cb、crc32ch、crc32cw、crc32cx 取代 x86 的 CRC32 系列汇编指令,替换方法如表所示,并在编译时添加编译参数-mcpu=generic+crc。



示例:


在 x86 下的实现:



在 ARM64 平台下的实现:


2.3 替换 x86 bswap 汇编指令

现象描述


编译报错:Error:unknown mnemonic bswap' --bswap x3’。


可能原因


bswap 是 x86 的字节序反序指令,需替换为 ARM64 的 rev 指令。


处理步骤


x86 指令实现的 bswap 如下:



替换为 ARM64 指令后如下:


2.4 替换 x86 rep 汇编指令

现象描述


编译报错:unknownmnemonic reprep


可能原因


rep 为 x86 的重复执行指令,需替换为 ARM64 的 rept 指令。


处理步骤


替换方法如下:


替换前:



替换后:


2.5 快速移植内联 SSE/SSE2 应用

现象描述


部分应用采用了 gcc 封装的用 SSE/SSE2 实现的函数,但是 gcc 目前没有提供对应的 ARM64 平台版本,需要实现对应函数。


处理步骤


目前已有开源代码实现了部分 ARM64 平台的函数,代码下载地址:https://github.com/open-estuary/sse2neon.git


使用方法如下:


步骤 1 将下载项目中的 SSE2NEON.h 文件拷贝到待移植项目中。


步骤 2 在源文件中删除如下代码。



步骤 3 在源代码中包含头文件 SSE2NEON.h


----结束

2.6 弱内存序导致程序执行结果和预期不一致

现象描述


弱内存序导致程序执行结果和预期不一致。


可能原因


ARM64 平台是弱内存序,原理如下:


  1. 同一份数据,在 cache 里面存在多份,需要 CPU 之间进行同步。



  1. 代码编写顺序和执行顺序可能不一样。



CPU 内部是流水线执行,在执行到 x=1 时,如果 x 在内存,那么 CPU 就会等待 x 导入到 cache,在等待的过程中如果 y 已经在 cache 中了,那么 CPU 会执行 y=1,这样就导致后面的语句先执行。


对系统的影响


  • 影响无锁编程的代码。

  • 对于使用信号量机制写的互斥代码,因为信号量函数已经带了内存屏障的指令,所以无影响。


处理步骤


找到使用无锁编程的代码,检查是否用内存屏障指令保证了数据的一致性。


使用内存屏障指令保证对共享数据的访问和预期一致。


示例:


2.7 对结构体中的变量进行原子操作时程序异常 coredump

现象描述


程序调用原子操作函数对结构体中的变量进行原子操作,程序 coredump,堆栈如下:



可能原因


ARM64 平台对变量的原子操作、锁操作等用到了 ldaxr、stlxr 等指令,这些指令要求变量地址必须按变量长度对齐,否则执行指令会触发异常,导致程序 coredump。


一般是因为代码中对结构体进行强制字节对齐,导致变量地址不在对齐位置上,对这些变量进行原子操作、锁操作等会触发问题。


处理步骤


代码中搜索“#pragmapack”关键字(该宏改变了编译器默认的对齐方式),找到使用了字节对齐的结构体,如果结构体中变量会被作为原子操作、自旋锁、互斥锁、信号量、读写锁的输入参数,则需要修改代码保证这些变量按变量长度对齐。

2.8 核数目硬编码

TaiShan 服务器相对于 x86 服务器,CPU 核数会有变化,如果模块代码针对处理器 core 数目硬编码,则会造成无法充分利用系统能力的情况,例如 CPU 核的利用率差异大或者绑核出现跨 numa 的情况。


处理步骤


您可以通过搜索代码中的绑核接口(sched_setaffinity)来排查绑核的实现是否存在 CPU 核数硬编码的情况。


如果存在,则根据 TaiShan 服务器实际核数进行修改,消除硬编码,可通过接口(sysconf(_SC_NPROCESSORS_CONF))来获取实际核数再进行绑核。

2.9 双精度浮点型转整型时数据溢出,与 X86 平台表现不一致

现象描述


C/C++双精度浮点型数转整型数据时,如果超出了整型的取值范围,TaiShan 平台的表现与 x86 平台的表现不同。



可能原因


在两个平台下,是两套 CPU 架构,其中的算数逻辑单元的实现可能会有差异,操作系统、编译器的实现都会有所不同。x86(指令集)中的浮点到整型的转换指令,定义了一个 indefinite integer value——“不确定数值”(64bit:0x8000000000000000),大多数情况下 x86 平台确实都在遵循这个原则,但是在从 double 向无符号整型转换时,又出现了不同的结果。鲲鹏的处理则非常清晰和简单,在上溢出或下溢出时,保留整型能表示的最大值或最小值,开发者并不会面对不确定或无法预期的结果。


处理步骤


参考如下数据转换的表格,调整代码中的实现:


double 数据向 long 转换:



double 数据向 unsigned long 转换:



double 数据向 int 转换:



double 数据向 unsigned int 转换:


编译优化项

4.1 gcc 编译器优化浮点运算精度

现象描述


编译优化选项设置-O2 级别及以上时,相同的浮点数乘加运算在 x86 平台和 ARM64 平台的运算结果,在小数点后 16 位存在差异。


可能原因


ARM64 平台编译优化选项设置为-O2 级别及以上,进行浮点数的乘加运算(a+=b*c),运算结果的精度只能精确到小数点后 16 位。在配置-O2 选项时,gcc 使用融合指令 fmadd 完成乘加运算,而不是 fadd 和 fmul。


fmadd 将浮点数的乘法和加法看成不可分的一个操作,不对中间结果进行舍入,从而导致计算结果有所差别。


对系统的影响


编译优化选项设置-O2 级别及以上时,浮点乘加运算的性能有提升,但是运算的精度受到影响。


处理步骤


添加编译选项-ffp-contract=off 可以关闭该优化。

4.2 增加编译选项匹配 Kunpeng 处理器架构,提升性能

在编译时增加编译选项指定处理器架构为 armv8,使编译器按照 Kunpeng 处理器的架构和微架构生成可执行程序,提升性能。


处理步骤


编译选项中添加-march=armv8-a。

4.3 增加编译选项匹配 Kunpeng 处理器流水线,提升性能

如果使用了 gcc 9.1 以上的版本,在编译时增加编译选项指定使用 tsv110 流水线,使编译器按照 Kunpeng 处理器的流水线编排指令执行顺序,充分利用流水线的指令集并行,提升性能。


处理步骤


编译选项中添加 -mtune=tsv110。


本文转载自公众号华为开发者社区(ID:Huawei_Developer)。


原文链接:


https://mp.weixin.qq.com/s/_-6H99jfp8D-MIm3GIcpWQ


2019-09-29 16:281888

评论

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

“信息茧房”里的人

架构精进之路

程序员 自我思考

拿着锤子的人,哪里都是钉子

Neco.W

思维方式 思考力

漫画通信:惊呆了,手机登录还可以这么玩!

阿里云Edge Plus

云通信 通信 通信云

分布式柔性事务之事务消息详解

奈学教育

分布式事务

一个典型的大型互联网应用系统使用了哪些技术方案和手段,主要解决什么问题?请列举描述。

Carlos

HTTP 的15个常见知识点复习

Geek_z9ygea

Java 大前端 Web HTTP

《机器学习理论导引》阅读攻略

华章IT

学习 周志华

使用 Prometheus-Operator 监控 Calico

硅基新手村

Prometheus calico

架构师训练营第四章作业

饶军

Prometheus 存储层的演进

伴鱼技术团队

性能优化 系统架构 Prometheus 存储 时序数据库

架构师训练营第四章作业

叮叮董董

架构 技术方案 解决手段 互联网架构

第四周直播总结笔记

Carlos

分布式柔性事务之事务消息详解

古月木易

分布式柔性事务‘’

围绕 Office 365 的那些 CLI

手艺人杨柳

Office 365

万字长文,让 Java 程序员入门小众语言 Ruby

Phoenix

Java ruby 个人成长 编程语言

深入浅出Shiro系列

程序员的时光

架构师训练营第四章总结

叮叮董董

总结 架构师 训练营

一路“开挂”,完美诠释“年少有为”——90 后首席科学家王乃岩

二叉树视频

写作平台 二叉树 年少有为

week04 学习总结 互联网面临挑战和架构模式

Z冰红茶

第四周总结

石刻掌纹

爱恨交织的红黑树

ytao

数据结构 算法

计算机操作系统基础(六)---作业管理之进程调度

书旅

Java php 多线程 操作系统 进程

架构5班3-4组优秀作业

tracy

项目域名配置流程

打鱼小王子

为什么美国程序员工作比中国程序员工作轻松、加班少?

程序员生活志

程序员 加班

以应用为中心:开放应用模型(OAM)初探

郭旭东

Kubernetes OAM

第四周作业

技术小生

极客大学架构师训练营

设计模式

Jeff

大型互联网应用技术方案

石刻掌纹

架构师训练营第4周作业

时来运转

架构师训练营第 4 周 总结

时来运转

TaiShan服务器代码移植经验分享_文化 & 方法_InfoQ精选文章