InfoQ|这篇文章给你答案,为什么必须将代码从x86迁移到ARM( 三 )


编译脚本和编译选项的移植:以x86下-m64代码为例 , 其主要功能是将应用程序编译为64位 , 对应到鲲鹏上是用-mabi=lp64的编译选项 , 此类编译选项需要在脚本中修改;此外 , x86平台上默认的char类型是一种有符号的类型 , 对应到鲲鹏上则是无符号类型 , 在移植过程中需要显示定义并将char类型定义为有符号 , 方法一是在源代码里加上signedchar , 方法二是直接用fsigned-char来修改 。
编译宏的移植:编译宏的作用就是让编译器知道编译哪些分支代码能够在不同架构下达到最优性能 。 如何对编译宏下面的代码实现移植?86代码上有些编译器自带自定义宏 , 比如smd属性相关的宏在x86上是SSE开头的宏 , 对应到鲲鹏平台上就需要自定义它的编译宏和所相对应的分支 。
Builtin函数移植:Builtin函数是编译器自带的函数 , 其在实际迁移项目中相当常见 , 主要是crc32校验值的计算 。 需要移植的普通builtin函数实际并不多 , 大部分需移植的builtin函数集中在SSEintrinsic函数内 。
内联汇编函数的移植:第一种是指令替换 , x86上对应的是bswap指令 , 鲲鹏对应的是rev指令 , 其它有些操作和寄存器都是基于内联汇编的语法规则进行替换的 。 第二种是Builtin函数的替换 , 以x86的指令popcnt为例 , 比如popcount是对二进制数里面的1进行计数 , 对应到鯤鹏平台上所替换的是popcountll 。
SSEintrinsic函数移植(SIMD技术):Intel的SIMD扩展指令统称SSE , 主要分为三类 , MMX是64位寄存器 , SSE到SSE4是28位的 , 三是AVX256和AVX512 。 鯤鹏基于SIMD的技术发展比较成熟 , 现在有些基于开源量的NEON库主要是在图象处理和视频处理层面 。
SSEintrinsic函数移植(MMX/SSE):针对MMX指令 , x86上用的是-m64的向量做加法运算 , 对应到鲲鹏上是int32×2然后再做加法运算 , 类似于常用的C函数规则;针对SSE指令 , 从内存中加载4个单精度浮点数据到寄存器 , x86是load , 对应到鲲鹏用的是vld1q 。
SSEintrinsic函数移植(AVX):以AVX指令使用了256位寄存器运算为例 , 向量A和向量B中分别存储了8个单精度浮点型(32位) , 对应到鲲鹏处理器上 , 使用128位寄存器实现SIMD(SingleInstructionMultiData)进行计算 。
尽管解释性语言难度降低 , 但Java、Python代码迁移过程中同样有一些问题需要注意 。
InfoQ|这篇文章给你答案,为什么必须将代码从x86迁移到ARM
文章图片
如上图所示 , Java想要进行迁移的话 , 首先需要安装运行环境JDK , Java源码通过Java编译器之后就会生成一个Java的字节码 , 这时候可能jar包会有一些SO库的依赖 , 那就需要链接进行打包 。
这整个的过程 , 存在迁移修改点的地方有二 , 一是JDK的安装 , 迁移过来推荐使用华为的JDK或者OpenJDK;二是对SO库这个二进制库的依赖 , 如果你是在x86下编译的 , 毫无疑问 , 这在鲲鹏下面是没办法进行运行的 , 所以你需要拿到相应的源码或者找到aarch64的SO库来进行替换 , 最后进行重新打包 。
再来看Python源码的迁移 , 其实与Java很类似 , 也是需要从编译环境和SO库两大方面入手修改 。 环境上推荐使用A32 , Python3你也可以通过样本安装 , 也可以通过源码安装;SO库有多种类型 , 但对于各种方式的SO库 , 最后都是对应为一个SO , 定义为SO库 , 需要的步骤也都是一致的 , 即装配环境、重新编译、重新替换 。
不同的地方只是前面安装的是Python的运行环境 。 Python源码同样通过解释器生成一个字节码 , 这时候可能我们会依赖外部的一些Pythonimport模块进来 , 这些模块里面可能有一些SO库 , Python解释器的解释执行后就是部署运行了 。
相对于C++来说 , Java/Python的迁移点并不是太多 , 总结下来 , 主要需要注意两点:


推荐阅读