為什么必須將代碼從x86遷移到ARM,這篇文章給你答案

“我們非常希望ARM和鯤鵬的生態(tài)能成為下一個(gè)計(jì)算產(chǎn)業(yè)迭代的方向。”在6月8日于成都舉辦的華為DevRun開發(fā)者沙龍——四川鯤鵬開發(fā)者嘉年華上,華為鯤鵬計(jì)算產(chǎn)業(yè)開源與生態(tài)營銷總監(jiān)梁冰對(duì)計(jì)算產(chǎn)業(yè)未來展望道。

新基建風(fēng)口下,算力一躍成為了新的生產(chǎn)力,云、AI與5G則是新的生產(chǎn)工具,技術(shù)聚變將引發(fā)商業(yè)裂變,帶動(dòng)各行各業(yè)的數(shù)字化快速發(fā)展?;?G等新興技術(shù)的創(chuàng)新應(yīng)用催生多樣化算力的需求,市場既需要通用計(jì)算算力也需要異構(gòu)計(jì)算算力。此外,摩爾定律的逐漸放緩,讓算力和性能陷入一系列發(fā)展瓶頸,市場對(duì)創(chuàng)新架構(gòu)的需求日益加深,計(jì)算平臺(tái)的創(chuàng)新之戰(zhàn)一觸即發(fā)。

在此背景下,x86架構(gòu)的不足越發(fā)明顯,功耗大、通用寄存器數(shù)量少、計(jì)算機(jī)硬件利用率低、尋址范圍小等問題凸顯,難以跟上算力發(fā)展的速度。與此同時(shí),ARM架構(gòu)在移動(dòng)互聯(lián)網(wǎng)盛行的當(dāng)下卻開始煥發(fā)出別樣的生命力。

“基于ARM架構(gòu)來設(shè)計(jì)的鯤鵬,其成功的前提是早早地便看到了未來計(jì)算機(jī)算力架構(gòu)的迭代之路。對(duì)華為來說,不光要在中國攜手合作伙伴共建鯤鵬生態(tài),為更多企業(yè)帶來價(jià)值,更為重要的是要融入全球ARM的生態(tài),共同推進(jìn)ARM進(jìn)階為下一代計(jì)算機(jī)平臺(tái)的事實(shí)標(biāo)準(zhǔn)。”梁冰對(duì)鯤鵬生態(tài)的意義闡述道。

從x86遷移到ARM架構(gòu)的過程并不簡單,本次活動(dòng)中,華為鯤鵬計(jì)算專家對(duì)于鯤鵬軟件遷移路徑也進(jìn)行了非常全面細(xì)致的講解,同時(shí)針對(duì)軟件遷移過程中可能遇到的問題及解決方案也進(jìn)行了相關(guān)講解,還為現(xiàn)場開發(fā)者設(shè)置了實(shí)操演練環(huán)節(jié),一對(duì)一指導(dǎo)下進(jìn)行鯤鵬軟件遷移線上實(shí)驗(yàn)。

從x86向鯤鵬遷移的必要性

眾所周知,計(jì)算機(jī)是由軟件和硬件組成的,上層的軟件是通過指令集驅(qū)動(dòng)下層的硬件,軟件想要跑在CPU上的話,那它必須要有對(duì)應(yīng)的指令集。

為什么必須將代碼從x86遷移到ARM,這篇文章給你答案

如上圖所示,整個(gè)計(jì)算機(jī)的計(jì)算基礎(chǔ)架構(gòu),從底層的晶體管、物理原材料,二極管也就是邏輯門電路,到往上走的微架構(gòu)、自評(píng)級(jí)架構(gòu),再往上面走就到了操作系統(tǒng)所完成的二進(jìn)制機(jī)器譯碼匯編高級(jí)語言、JavaC等等,整個(gè)技術(shù)站從復(fù)雜到抽象,技術(shù)語言也從經(jīng)歷一個(gè)簡單的交換指令發(fā)展為匯編進(jìn)行訪存和鎖存,再到形成機(jī)器碼,這個(gè)過程中最核心的變化在指令集上。

想要成功運(yùn)行,底層計(jì)算平臺(tái)就必須能夠支持該 CPU 的指令才可以,這也是在 x86 和鯤鵬編譯的不同之處。

為什么必須將代碼從x86遷移到ARM,這篇文章給你答案

如上圖所示,x86和鯤鵬使用的指令是不一樣的,簡單來講,在鯤鵬上使用的是精簡指令集,而在x86上使用的是一個(gè)復(fù)雜的指令集。綜合來講,它有三點(diǎn)主要的差異:

架構(gòu)差異:x86和鯤鵬處理器(aarch64)屬于不同的架構(gòu)。

指令集差異:x86--復(fù)雜指令集,鯤鵬處理器--精簡指令集。

向量寄存器差異:x86和鯤鵬處理器使用向量寄存器不同,向量指令集也存在差異。

從這三點(diǎn)出發(fā),一個(gè)在x86上運(yùn)行的程序根本不可能毫無阻礙地就可以在鯤鵬上使用,必須經(jīng)過編譯,同時(shí)也證明了遷移的必要性。

遷移的五個(gè)步驟

為什么必須將代碼從x86遷移到ARM,這篇文章給你答案

1.遷移準(zhǔn)備:信息收集&環(huán)境申請(qǐng)

信息的收集主要分為兩部分,首先是硬件信息的收集,主要就是一些型號(hào),目的是根據(jù)此類信息匹配一個(gè)x86的服務(wù)器;其次是收集軟件棧信息,包括操作系統(tǒng)、虛擬機(jī)、中間件、編譯器、上層依賴的開源軟件、商業(yè)軟件、業(yè)務(wù)軟件等信息。

2.遷移分析:軟件棧分析&編程語言分析

這一過程要做的就是對(duì)收集到的信息和軟件棧做初步分析,目的是判斷是否真正需要遷移,評(píng)估遷移的工作量。

對(duì)開源軟件來說,因?yàn)樯鐓^(qū)發(fā)展已經(jīng)比較成熟,遷移相對(duì)較為簡單,通過基于鯤鵬的架構(gòu)分支或者鯤鵬支持的軟件包,自行安裝即可。對(duì)于自研軟件來講,情況則較為復(fù)雜,如C、C++這類編譯型軟件,從指令集差異化出發(fā),需要重新編譯后才能完成遷移,而Java、Python這種解釋型的語言,因?yàn)槠涮摂M機(jī)如JDK、PVM已經(jīng)把上層的一些跟指令集相關(guān)的東西屏蔽掉了,平滑地遷移過去即可。對(duì)于商用軟件而言,不會(huì)公開源碼,如果需要遷移,就必須要聯(lián)系廠家去編譯一個(gè)鯤鵬的版本,并且完成一系列的適配。

此外像運(yùn)行環(huán)境、虛擬機(jī)、編譯器和操作系統(tǒng)這些也是要進(jìn)行替換,但是這些并非需要重新編譯,因?yàn)樵谌A為云鯤鵬論壇內(nèi)有軟件倉庫,可以直接去軟件倉庫下載由鯤鵬官方所做的經(jīng)過驗(yàn)證的版本。

3.編譯遷移:代碼遷移&軟件包遷移

編譯型的語言,之所以遷移起來比較困難,原因就在于涉及到比較多的遷移點(diǎn),下面將從代碼和軟件包兩方面進(jìn)行闡述。

對(duì)于對(duì)指令集有依賴的代碼來說,與x86架構(gòu)相關(guān)的,都需要替換成ARM架構(gòu)下的語言;像以Java、Python為代表的解釋型語言,換一下JDK和PVM就行了,如果語言中調(diào)用了編譯型語言,必須把這部分重新編譯才可行。對(duì)于軟件包來說,其遷移與Java、Python語言類似,即掃描出來里邊的對(duì)編譯型語言的依賴,把這一部分依賴進(jìn)行替換即可。

4.性能調(diào)優(yōu):性能指標(biāo)測試&性能優(yōu)化

經(jīng)過前面幾個(gè)步驟之后,軟件遷移其實(shí)就基本完成了,之后要對(duì)性能進(jìn)行調(diào)優(yōu),主要分為建立基準(zhǔn) 、壓力測試 、確定瓶頸、 實(shí)施優(yōu)化、 確認(rèn)效果五個(gè)步驟。

首先需要建立調(diào)優(yōu)基準(zhǔn),該基準(zhǔn)根據(jù)當(dāng)前的硬件配置、組網(wǎng)、測試模型來做綜合評(píng)估,以建立合理的條有目標(biāo);其次在調(diào)優(yōu)目標(biāo)建立后,通過壓測工具對(duì)軟件或系統(tǒng)進(jìn)行加壓,在加壓過程中暴露性能瓶頸,確定瓶頸之后對(duì)瓶頸進(jìn)行優(yōu)化;第四,注意在優(yōu)化過程中要及時(shí)記錄,因?yàn)閮?yōu)化并不一定是正向的,出現(xiàn)負(fù)向優(yōu)化時(shí)需要及時(shí)回退;最后在優(yōu)化措施實(shí)施完成后,需要重新啟動(dòng)壓力測試工具以確認(rèn)優(yōu)化效果。

5.測試與認(rèn)證:壓力測試&長穩(wěn)測試&規(guī)模商用

調(diào)優(yōu)結(jié)束之后,接下來就要把功能運(yùn)力、長穩(wěn)運(yùn)力以及性能運(yùn)力都跑一遍,達(dá)到一個(gè)商用的標(biāo)準(zhǔn),就可以籌備上線了。此外也可以將軟件和系統(tǒng)進(jìn)行鯤鵬展翅認(rèn)證,其可以擴(kuò)展應(yīng)用的軟件使用空間并能夠加入鯤鵬生態(tài)。

不同語言的遷移注意事項(xiàng)

實(shí)際上,像Java、Python、Perl這種跨平臺(tái)的開發(fā)語言,它的遷移的技術(shù)難度相對(duì)來說是比較低的,主要是因?yàn)镴ava有一個(gè)JBM,Python中存在一個(gè)解釋器,它們屏蔽了大部分的平臺(tái)架構(gòu)上的差異。與之相反,C和C++的難度相對(duì)來說要高一些,原因是如內(nèi)斂函數(shù)還有x86加速的一些指令,無法支持像微軟這種閉源的開發(fā)架構(gòu)。

典型的如C/C++/Go語言,都屬于編譯型語言。編譯型語言開發(fā)的程序在從x86處理器遷移到鯤鵬處理器時(shí),必須經(jīng)過重新編譯才能運(yùn)行。如下圖所示,源碼需要由編譯器、匯編器翻譯成機(jī)器指令,再通過鏈接器鏈接庫函數(shù)才能生成機(jī)器語言程序。

為什么必須將代碼從x86遷移到ARM,這篇文章給你答案

接下來就是C/C++代碼的編譯構(gòu)建了,這個(gè)過程一共分為六步:

獲取源碼:通過github或第三方開源社區(qū)獲取

準(zhǔn)備編譯環(huán)境:安裝編譯器gcc等

使用源碼中的CMakeLists.txt或configure腳本生成makefile

執(zhí)行makefile編譯可執(zhí)行程序

替換依賴庫:重編譯或替換依賴x86平臺(tái)的so庫

將可執(zhí)行程序安裝部署到生產(chǎn)或測試系統(tǒng)

既然是最為復(fù)雜的,C/C++語言的遷移問題也是涉獵最廣泛的,主要涉及到七類問題:

編譯腳本和編譯選項(xiàng)的移植:以x86 下 -m64 代碼為例,其主要功能是將應(yīng)用程序編譯為 64 位,對(duì)應(yīng)到鯤鵬上是用 -mabi=lp64 的編譯選項(xiàng),此類編譯選項(xiàng)需要在腳本中修改;此外, x86 平臺(tái)上默認(rèn)的 char 類型是一種有符號(hào)的類型,對(duì)應(yīng)到鯤鵬上則是無符號(hào)類型,在移植過程中需要顯示定義并將 char 類型定義為有符號(hào),方法一是在源代碼里加上 signed char,方法二是直接用 fsigned-char 來修改。

編譯宏的移植:編譯宏的作用就是讓編譯器知道編譯哪些分支代碼能夠在不同架構(gòu)下達(dá)到最優(yōu)性能。如何對(duì)編譯宏下面的代碼實(shí)現(xiàn)移植?86 代碼上有些編譯器自帶自定義宏,比如 smd 屬性相關(guān)的宏在 x86 上是 SSE 開頭的宏,對(duì)應(yīng)到鯤鵬平臺(tái)上就需要自定義它的編譯宏和所相對(duì)應(yīng)的分支。

Builtin 函數(shù)移植:Builtin 函數(shù)是編譯器自帶的函數(shù),其在實(shí)際遷移項(xiàng)目中相當(dāng)常見,主要是 crc32 校驗(yàn)值的計(jì)算。需要移植的普通 builtin 函數(shù)實(shí)際并不多,大部分需移植的 builtin 函數(shù)集中在 SSE intrinsic 函數(shù)內(nèi)。

內(nèi)聯(lián)匯編函數(shù)的移植:第一種是指令替換,x86 上對(duì)應(yīng)的是 bswap 指令,鯤鵬對(duì)應(yīng)的是 rev 指令,其它有些操作和寄存器都是基于內(nèi)聯(lián)匯編的語法規(guī)則進(jìn)行替換的。第二種是Builtin函數(shù)的替換,以x86的指令popcnt為例,比如 popcount 是對(duì)二進(jìn)制數(shù)里面的 1 進(jìn)行計(jì)數(shù),對(duì)應(yīng)到鯤鵬平臺(tái)上所替換的是 popcountll。

SSE intrinsic 函數(shù)移植(SIMD 技術(shù)):Intel 的 SIMD 擴(kuò)展指令統(tǒng)稱 SSE,主要分為三類,MMX 是 64 位寄存器,SSE 到 SSE4 是 28 位的,三是 AVX256 和 AVX512。鯤鵬基于 SIMD 的技術(shù)發(fā)展比較成熟,現(xiàn)在有些基于開源量的 NEON 庫主要是在圖象處理和視頻處理層面。

SSE intrinsic 函數(shù)移植(MMX/SSE):針對(duì)MMX指令,x86 上用的是 -m64 的向量做加法運(yùn)算,對(duì)應(yīng)到鯤鵬上是 int32×2 然后再做加法運(yùn)算,類似于常用的 C 函數(shù)規(guī)則;針對(duì) SSE 指令,從內(nèi)存中加載 4 個(gè)單精度浮點(diǎn)數(shù)據(jù)到寄存器,x86 是 load,對(duì)應(yīng)到鯤鵬用的是 vld1q。

SSE intrinsic 函數(shù)移植(AVX):以 AVX 指令使用了 256 位寄存器運(yùn)算為例,向量 A 和向量 B 中分別存儲(chǔ)了 8 個(gè)單 精度浮點(diǎn)型 (32 位),對(duì)應(yīng)到鯤鵬處理器上,使用 128 位寄存器實(shí)現(xiàn) SIMD(Single Instruction Multi Data) 進(jìn)行計(jì)算。

盡管解釋性語言難度降低,但Java、Python代碼遷移過程中同樣有一些問題需要注意。

為什么必須將代碼從x86遷移到ARM,這篇文章給你答案

如上圖所示,Java想要進(jìn)行遷移的話,首先需要安裝運(yùn)行環(huán)境JDK,Java源碼通過Java編譯器之后就會(huì)生成一個(gè)Java的字節(jié)碼,這時(shí)候可能jar包會(huì)有一些SO庫的依賴,那就需要鏈接進(jìn)行打包。

這整個(gè)的過程,存在遷移修改點(diǎn)的地方有二,一是JDK的安裝,遷移過來推薦使用華為的JDK或者OpenJDK;二是對(duì)SO庫這個(gè)二進(jìn)制庫的依賴,如果你是在x86下編譯的,毫無疑問,這在鯤鵬下面是沒辦法進(jìn)行運(yùn)行的,所以你需要拿到相應(yīng)的源碼或者找到aarch64的SO庫來進(jìn)行替換,最后進(jìn)行重新打包。

再來看Python源碼的遷移,其實(shí)與Java很類似,也是需要從編譯環(huán)境和 SO 庫兩大方面入手修改。環(huán)境上推薦使用 A32,Python3 你也可以通過樣本安裝,也可以通過源碼安裝;SO 庫有多種類型,但對(duì)于各種方式的 SO 庫,最后都是對(duì)應(yīng)為一個(gè) SO,定義為 SO 庫,需要的步驟也都是一致的,即裝配環(huán)境、重新編譯、重新替換。

不同的地方只是前面安裝的是Python的運(yùn)行環(huán)境。Python源碼同樣通過解釋器生成一個(gè)字節(jié)碼,這時(shí)候可能我們會(huì)依賴外部的一些Python import模塊進(jìn)來,這些模塊里面可能有一些SO庫,Python解釋器的解釋執(zhí)行后就是部署運(yùn)行了。

相對(duì)于C++來說,Java/Python的遷移點(diǎn)并不是太多,總結(jié)下來,主要需要注意兩點(diǎn):

編譯器包括解釋器的安裝、遷移,這里有兩種方式,方式一是通過YAM源的方式進(jìn)行安裝,方式二是找到源碼進(jìn)行編譯重新安裝。

x86依賴SO庫的情況下,需要找到SO庫相應(yīng)的源碼,進(jìn)行重新編譯后實(shí)現(xiàn)替換。

寫在最后

“拿華為的話說,就是自己的降落傘自己先跳。長虹大數(shù)據(jù)平臺(tái)的規(guī)模比較大,有一百多個(gè)服務(wù)器,原來是一個(gè)PB級(jí)的數(shù)據(jù)存儲(chǔ),涉及到的整個(gè)生態(tài)組件有20多個(gè),我們將原來存在的1700多萬的終端業(yè)務(wù)遷移到基于鯤鵬的大數(shù)據(jù)計(jì)算平臺(tái),耗時(shí)近5個(gè)月。鯤鵬的架構(gòu)在HBS場景下優(yōu)勢凸出,另外在存儲(chǔ)、IO等方面基本上是持平,總體來說,鯤鵬的芯片表現(xiàn)性能都還不錯(cuò)。”長虹計(jì)算產(chǎn)業(yè)事業(yè)部技術(shù)總監(jiān)蒲文龍這樣評(píng)價(jià)到同行者華為鯤鵬。

無獨(dú)有偶,麒麟軟件有限公司技術(shù)總監(jiān)李洋同樣贊揚(yáng)道,“華為鯤鵬的代碼遷移工具,包括分析掃描工具、代碼遷移工具及性能優(yōu)化工具,這是作為開發(fā)者一定要去了解的非常方便的工具,它可以讓開發(fā)者快速地分析系統(tǒng)軟件源代碼,以及對(duì)所需要的依賴包進(jìn)行編譯和重構(gòu)。”

對(duì)于開發(fā)者來說,遷移是一套必須掌握的技能;對(duì)于互聯(lián)網(wǎng)企業(yè)來說,遷移是助力企業(yè)抓住未來趨勢的一個(gè)必要?jiǎng)幼?。從x86架構(gòu)到ARM架構(gòu),計(jì)算產(chǎn)業(yè)的未來已經(jīng)漸漸明晰,而鯤鵬作為先行者,生態(tài)的力量也愈發(fā)強(qiáng)大,始終秉持著“硬件開放、軟件開源、使能伙伴”的初心,逐漸發(fā)展成為滋養(yǎng)新計(jì)算產(chǎn)業(yè)的一方沃土。

(免責(zé)聲明:本網(wǎng)站內(nèi)容主要來自原創(chuàng)、合作伙伴供稿和第三方自媒體作者投稿,凡在本網(wǎng)站出現(xiàn)的信息,均僅供參考。本網(wǎng)站將盡力確保所提供信息的準(zhǔn)確性及可靠性,但不保證有關(guān)資料的準(zhǔn)確性及可靠性,讀者在使用前請(qǐng)進(jìn)一步核實(shí),并對(duì)任何自主決定的行為負(fù)責(zé)。本網(wǎng)站對(duì)有關(guān)資料所引致的錯(cuò)誤、不確或遺漏,概不負(fù)任何法律責(zé)任。
任何單位或個(gè)人認(rèn)為本網(wǎng)站中的網(wǎng)頁或鏈接內(nèi)容可能涉嫌侵犯其知識(shí)產(chǎn)權(quán)或存在不實(shí)內(nèi)容時(shí),應(yīng)及時(shí)向本網(wǎng)站提出書面權(quán)利通知或不實(shí)情況說明,并提供身份證明、權(quán)屬證明及詳細(xì)侵權(quán)或不實(shí)情況證明。本網(wǎng)站在收到上述法律文件后,將會(huì)依法盡快聯(lián)系相關(guān)文章源頭核實(shí),溝通刪除相關(guān)內(nèi)容或斷開相關(guān)鏈接。 )