近年来信创工作和国产化开展的如火如荼,而将应用由X86服务器迁移到华为鲲鹏等ARM系CPU的服务器上一直是一个比较困难的环节,这方面我在工作中还是做了很多工作与预研的,那么这里我就把一些探索和预研中所遇到的一些问题分享给大家,避免大家踩坑。X86向ARM移植困难归其根本原因有两大方面,一是这两种CPU在处理某些类型的溢出时,行为不同,二是由于X86与ARM分与不同的复杂指令集与精简指令集阵营,因此他们的机器指令不能完全一一对应,而部分项目为加速运行效率会使用汇编语言直接编写机器指令以最大程度的对程序进行优化,这也就使得汇编语言部分的代码移植起来非常麻烦。

先说一下结论:

移植起来较为简单的应用类型:

  1. 纯的Java、Python等高级语言开发的程序,比如jetty等web容器
  2. 无状态的比较适合容器化部署的应用,如Nginx。

移植难度中等的应用类型:

  1. C、GO语言编写且不太合适容器化部署的应用
  2. Java与C混合编写,而C语言的部分没有内联汇编代码的应用。

移植难度较高的应用类型:

  1. C为主体,但内联汇编语言进行优化的应用
  2. Java与C混合,且C语言的部分中内联了汇编代码的应用

坑点一. unsign char问题

-这里先说一下原码,补码的概念。比如1 的二进制原码是 10000001,它的补码是除了符号外取反加 1,最后补码就是 11111111。 在 X86 架构下,char 默认是有符号的,所以打印的时候正常打印-1;但是在ARM下 char 默认是无符号的,这个二进制的 11111111 正好就是无符号的 255。所以需要注意在ARM编译程度时,加入-fsigned-char 编译选项以避免这个问题如下:

aarch64-redhat-linux-gcc -fsigned-char -o transfer *.c

坑点二:值溢出的问题

X86的CPU里浮点到整型的转换指令,定义了一个 indefinite integer value(0x8000000000000000),来处理溢出问题,但从 indefinite integer value中无法判断上溢出还是下溢出。 而这㢇ARM的处理策略则是无论是上溢出还是下溢出时,都保留整型所能表示的最大或最小值,具体对比如下:

CPU

double

转为long

变量保留值说明

x86

正值超出long

范围0x8000000000000000

indefinite integer value

x86

负值超出long

范围0x8000000000000000

indefinite integer value

鲲鹏

正值超出long

范围0x7FFFFFFFFFFFFFFF

变量所能表示最大的正数

鲲鹏

负值超出long

范围0x8000000000000000

变量所能表示最大的正数

因此对于C语言的项目中一定要特别注意进行溢出检查。

坟点三:.解决C语言代码中内联嵌入汇编指令的问题

由于X86架构属于CISC(复杂指令集)而ARM属于RISC(精简指令集)他们在汇编指令上完全不同,部分常用的X86指令在ARM体系下没有对应指令。尤其某些对于效率要求极高的X86体系程序经常用到如SSE、SSE2等多数据流的相关指令。

1、SSE、SSE2简介

SSE是单指令多数据流指令集的简称,对于64位计算机来说,一条经典的指令输入、都输出只能是一个64位长的数据,针对双精度(128位长)类型的变量只能分解成若干个64位数据处理。但是X86中提供了128位的寄存器,并通过SSE指令集提供了很多单指令操作128位数据的指令功能,也就是由单一指令处理双精度变量的服务,其输入、输出均是128位的字长,这极大的提升了X86体系CPU处理双精度数据的效率。

当然目前已有开源的项目实现了ARM平台的SSE相关函数(https://github.com/openestuary/sse2neon.git),按照其README来进行操作即可,但是因为此处涉及敏感信息,我不能把实测数据放上来,只能定性的说X86处理器中SSE指令的硬件实现效率很高,sse2neon项目只是实现了SSE的功能,却无法达到SSE的处理速度,这可能是鲲鹏等ARM系服务器需要更多核心才能与X86服务器对标运算能力的原因。

坑点四、XCHGL问题:

xchgl 是 x86 上的汇编指令,作用是交换内存变量的值,我们知道交换操作需要中间过渡,而且需要执行三条指令,即A->TMP,B->A,TMP->B三步才可完成,而这又是一个常用的X86汇编指令,单指令完成,而且属于原子操作。而鲲鹏上如果需要原子交换变量值,需要用glibc的原子操作接口__atomic_exchange_n 来进行,而且也还是存在刚刚说的效率问题。

虽然总结起来并不多,但这些坑点也真是耗费了很多时间才摸索出来的,通过此篇短文总结一下,希望对读者有所帮助。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐