写点什么

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:281694

评论

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

聚焦大模型基础设施发展,AI Infra组会在宁召开

中国信通院AI Infra工作组

如何将扫码提交的数据直接推送到企业微信、钉钉、飞书群聊?详细教程

草料二维码

草料二维码

2024 AIIA先锋案例 | AI Infra专项征集工作持续进行中

中国信通院AI Infra工作组

2024南京软件产业博览会(南京软博会)

AIOTE智博会

软件博览会 软件展会 软博会 南京软博会

提高软技能,财务团队发展的关键经验教训

智达方通

全面预算管理 财务管理 财务报告 管理会计信息化

基于ChatGPT开发人工智能服务平台

霍格沃兹测试开发学社

MES实时监控食品加工过程中各环节的安全

万界星空科技

工业互联网 mes 万界星空科技 食品MES 食品行业

火山引擎数智平台:高性能ChatBI的技术解读和落地实践

字节跳动数据平台

大数据 BI 数据可视化 大模型 ChatBI

华瑞指数云ExponTech与崖山科技达成战略合作,共筑国产数据库新生态

科技热闻

Suno 重磅功能「Covers」:一键翻唱任意歌曲;阿里通义将发布 AI 视频生成大模型丨 RTE 开发者日报

声网

反DDD模式之关系型数据库

EquatorCoco

数据库 DDD

用户需求瞬息万变?游戏直播平台快速开发应对方案

软件开发-梦幻运营部

前端是靠什么起家的?

伤感汤姆布利柏

数据驱动新时代:数据飞轮如何唤醒中台潜能

不叫猫先生

大数据 数据中台 数据仓库 数据飞轮

首批通过!中国移动(浙江)创新研究院九天信创一体机顺利通过中国信通院可信AI大模型一体机评估

中国信通院AI Infra工作组

万界星空科技AI低代码MES的具体功能及工厂应用效果

万界星空科技

低代码 低代码平台 mes 万界星空科技 低代码云MES

Java读取寄存器数据的方法

不在线第一只蜗牛

Java 数据库

阿里巴巴搜索API返回值:电商市场竞争的新武器

技术冰糖葫芦

API Gateway API 接口 API 测试 pinduoduo API

阿里巴巴API助力电商:商品详情获取与数据驱动的完美结合

技术冰糖葫芦

API Gateway API 接口 API 测试 pinduoduo API

Java获取Object中Value的方法

快乐非自愿限量之名

Java

首批通过!百度千帆大模型一体机顺利通过中国信通院可信AI大模型一体机全能力评估

中国信通院AI Infra工作组

Suno 重磅功能「Covers」:一键翻唱任意歌曲;阿里通义将发布 AI 视频生成大模型丨 RTE 开发者日报

声网

助力园区数字化转型,合合信息市北高新园区打造“一企一画像”个性化服务

合合技术团队

数字化转型 科技 合合信息

Node.js 扩展N-API 和应用场景

PingCode研发中心

node.js 应用场景

探讨微信小程序与移动应用的结合

Geek_2305a8

首批通过!华为FusionCube A3000训推超融合一体机通过中国信通院可信AI大模型一体机产品全能力评估

中国信通院AI Infra工作组

人工智能 | 基于ChatGPT开发人工智能服务平台

测吧(北京)科技有限公司

测试

什么是任务管理工具

爱吃小舅的鱼

深度挖掘|Cloudera安装不再难!基础环境搭建全解析

敏捷调度TASKCTL

cloudera CDH CDH 大数据 Hadoop

关于征集人工智能中台系列标准参编单位通知

中国信通院AI Infra工作组

从数据仓库到数据飞轮:数据技术演进的探索与思考

不叫猫先生

数据中台 数据仓库 数据 数据飞轮

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