《電子技術(shù)應(yīng)用》
您所在的位置:首頁 > 嵌入式技術(shù) > 設(shè)計(jì)應(yīng)用 > Go語言在國(guó)產(chǎn)CPU平臺(tái)上應(yīng)用前景的探索與思考
Go語言在國(guó)產(chǎn)CPU平臺(tái)上應(yīng)用前景的探索與思考
2018年電子技術(shù)應(yīng)用第8期
陳 希,胡 彬
國(guó)家工業(yè)信息安全發(fā)展研究中心,北京100040
摘要: 代表信息新時(shí)代的Go語言誕生了,它所具有的高并發(fā)性非常適合服務(wù)器編程,而其天生的跨平臺(tái)優(yōu)勢(shì),降低了分布式異構(gòu)計(jì)算平臺(tái)的開發(fā)難度,最終讓程序變得簡(jiǎn)潔、干凈、高效。對(duì)Go語言在國(guó)產(chǎn)平臺(tái)上的移植進(jìn)行探索,實(shí)測(cè)Go語言在龍芯和飛騰兩個(gè)國(guó)產(chǎn)平臺(tái)的多核調(diào)用功能,分析研判結(jié)果,得出結(jié)論,為未來Go語言在國(guó)產(chǎn)平臺(tái)的發(fā)展提供參考。
中圖分類號(hào): TP312
文獻(xiàn)標(biāo)識(shí)碼: A
DOI:10.16157/j.issn.0258-7998.181486
中文引用格式: 陳希,胡彬. Go語言在國(guó)產(chǎn)CPU平臺(tái)上應(yīng)用前景的探索與思考[J].電子技術(shù)應(yīng)用,2018,44(8):1-4,9.
英文引用格式: Chen Xi,Hu Bin. The exploration and thinking of the application of Go language on domestic CPU platform[J]. Application of Electronic Technique,2018,44(8):1-4,9.
The exploration and thinking of the application of Go language on domestic CPU platform
Chen Xi,Hu Bin
China Industrial Control Systems Cyber Emergency Response Team,Beijing 100040,China
Abstract: The Go language, which represents the new age of information, has a high degree of concurrency for server programming, and has natural cross-platform advantage, which reduces the difficulty of developing distributed heterogeneous computing platforms, and ultimately makes programs simple, clean and efficient. This paper will explore the transplanting of Go on the domestic platform, test the multi-nuclear function of the Go language in the dragon core and Phytium two domestic platforms, analyze the results, reach the conclusion, and provide reference for the future development of the Go language on the domestic platform.
Key words : polynuclear programming;domestic platform;complicated;multicore call

0 引言

    CPU是電子產(chǎn)品的核心,代表著信息產(chǎn)業(yè)的發(fā)展水平。CPU發(fā)展至今已經(jīng)有四十多年的歷史了,實(shí)際就是Intel公司的發(fā)展歷史[1]。Intel的CPU和其兼容產(chǎn)品占領(lǐng)了PC的大半江山。我國(guó)CPU戰(zhàn)略已經(jīng)發(fā)展十余年,部分領(lǐng)域完全具有核心技術(shù),產(chǎn)業(yè)化取得積極進(jìn)展,但是與國(guó)際主流廠商Intel等仍存在較大差距。國(guó)產(chǎn)CPU由于受多方因素制約,單核性能并不高,在2000年左右所有的微處理器廠商都轉(zhuǎn)向了多核微處理器的開發(fā)。為提升CPU性能,國(guó)產(chǎn)CPU均為多核設(shè)計(jì)。目前,部分產(chǎn)品雖然在黨政軍部門及重要的信息系統(tǒng)有所應(yīng)用,但是由于產(chǎn)業(yè)生態(tài)還未建立,所應(yīng)用的場(chǎng)景還比較簡(jiǎn)單,可用于開發(fā)應(yīng)用的編程語言也較為單一。國(guó)產(chǎn)CPU的發(fā)展事關(guān)我國(guó)信息產(chǎn)業(yè)的核心競(jìng)爭(zhēng)力和可持續(xù)發(fā)展力。為了充分發(fā)揮國(guó)產(chǎn)CPU的性能,需要通過并行編程來解決。

    Go語言設(shè)計(jì)目標(biāo)之一就是多核編程,不使用多線程編程模型,通過基于CSP的communication通道并發(fā)編程,使得并發(fā)編程更加簡(jiǎn)便。Go語言原生支持廣泛應(yīng)用的X86、X64指令集,而且支持龍芯的MIPS64及飛騰的ARM64指令集。這使得Go語言程序在跨平臺(tái)移植上天生具有優(yōu)勢(shì)。Go語言的其他一些特性使得其在國(guó)產(chǎn)CPU平臺(tái)應(yīng)用具有非常廣泛的前景。

1 Go語言簡(jiǎn)介

    Go語言是2009年11月Google正式宣布推出的一種編程語言。它的并發(fā)機(jī)制使得編寫能夠充分利用多核和網(wǎng)絡(luò)通信的程序變得非常容易。Go語言是靜態(tài)類型的語言,它的類型系統(tǒng)沒有層級(jí),完全垃圾回收,比典型的面向?qū)ο笳Z言更輕量級(jí);Go語言是一種編譯型語言,它結(jié)合了解釋型語言的游刃有余,動(dòng)態(tài)類型語言的開發(fā)效率,以及靜態(tài)類型的安全性。

    Go編譯器支持包括:x86、x64、ARM、arm64、ppc64、ppc64le、mips、mipsle、mips64、mips64le、s390x多種不同的CPU指令集??梢灾С职‵reeBSD、Linux、Solaris和Windows等的多種操作系統(tǒng)。Go語言是跨平臺(tái)、跨操作系統(tǒng)的語言,部署非常簡(jiǎn)單。Go 編譯生成的是一個(gè)靜態(tài)可執(zhí)行文件,除了glibc外沒有其他外部依賴。Go的并發(fā)性好,而且goroutine 和 channel 使得編寫高并發(fā)的服務(wù)端軟件變得相當(dāng)容易,非常適合用來服務(wù)器編程。目前Go語言已經(jīng)成功的項(xiàng)目包括目前比較流行的云框架Docker、NSQ等分布式框架等。

2 國(guó)產(chǎn)CPU平臺(tái)簡(jiǎn)介及應(yīng)用現(xiàn)狀

    目前,我國(guó)自主研發(fā)的處理器芯片主要包括龍芯(MIPS64指令集)、申威(Alpha指令集)、飛騰(ARM64指令集)及兆芯(X86指令集)4類。商用領(lǐng)域基于龍芯3B1500 CPU、飛騰FA1500A CPU生產(chǎn)的商用服務(wù)器占據(jù)國(guó)產(chǎn)服務(wù)器主流位置,龍芯、飛騰服務(wù)器分別搭載中標(biāo)麒麟及銀河麒麟操作系統(tǒng)。

    在商用領(lǐng)域,全國(guó)產(chǎn)化平臺(tái)剛剛起步,配套的商用軟件較少,沒有建立起完整的產(chǎn)業(yè)生態(tài),同時(shí)又受到處理器自身性能的影響,基于上述兩款主流處理器平臺(tái)的服務(wù)器,主要還是用于對(duì)系統(tǒng)訪問并發(fā)及響應(yīng)時(shí)間要求不高的Web網(wǎng)站類網(wǎng)絡(luò)應(yīng)用服務(wù)。國(guó)產(chǎn)處理器應(yīng)用服務(wù)的開發(fā)還是以Java語言為主,搭配開源JBoss、Ttomcat或國(guó)產(chǎn)中間件,數(shù)據(jù)庫(kù)采用國(guó)產(chǎn)數(shù)據(jù)庫(kù)或MySQL等開源數(shù)據(jù)庫(kù)。

3 Go語言在國(guó)產(chǎn)平臺(tái)的優(yōu)勢(shì)

3.1 國(guó)產(chǎn)平臺(tái)現(xiàn)有的編程語言匱乏

    目前,基于國(guó)產(chǎn)CPU的國(guó)產(chǎn)化平臺(tái)比較成熟的僅有C、C++編譯器。廠商對(duì)Java虛擬機(jī)在國(guó)產(chǎn)平臺(tái)上進(jìn)行編譯、適配及優(yōu)化。由于Java應(yīng)用運(yùn)行過程中依賴的大量Java第三方框架都是源于X86構(gòu)架體系,并未針對(duì)國(guó)產(chǎn)CPU進(jìn)行優(yōu)化,一些應(yīng)用在大壓力或大并發(fā)等某些場(chǎng)景下會(huì)出現(xiàn)假死、宕機(jī)等情況,嚴(yán)重影響應(yīng)用的正常運(yùn)行。雖然國(guó)產(chǎn)平臺(tái)也支持其他編程語言如Python、PHP等,但這類腳本語言的解釋器也是交叉編譯獲得的,并非自身支持,在進(jìn)行跨平臺(tái)交叉編譯過程中會(huì)遇到各種問題,很多問題需要軟件開發(fā)人員修改軟件源代碼,未經(jīng)過大量適配驗(yàn)證,很難保證其開發(fā)的應(yīng)用的穩(wěn)定性。

3.2 Go語言的跨平臺(tái)及并發(fā)優(yōu)勢(shì)

    Go語言原生支持龍芯CPU的MIPS64le指令集和飛騰CPU的ARM64指令集,天生具有跨平臺(tái)優(yōu)勢(shì)。Go開發(fā)應(yīng)用在任意平臺(tái)開發(fā)完成后,直接編譯,編譯后的二進(jìn)制文件在同類平臺(tái)可直接拷貝運(yùn)行,無需再次重新編譯。除了glibc外,無需其他外部依賴??梢灾苯釉谠撻_發(fā)平臺(tái)的任意計(jì)算機(jī)上運(yùn)行,無需像Java運(yùn)行那樣需要虛擬機(jī),需要配置復(fù)雜的環(huán)境變量;在作為網(wǎng)絡(luò)服務(wù)時(shí)更不需要像Tomcat、Apache等的Web中間件。

    Go語言的異構(gòu)平臺(tái)移植也非常簡(jiǎn)單,僅需要應(yīng)用程序的源碼,在異構(gòu)平臺(tái)上直接編譯即可,且編譯后的二進(jìn)制文件在同類平臺(tái)可直接拷貝運(yùn)行。Go語言本身就具有天生的跨平臺(tái)優(yōu)勢(shì),大大降低了分布式異構(gòu)計(jì)算平臺(tái)的開發(fā)難度,非常適合在目前多構(gòu)架的國(guó)產(chǎn)化平臺(tái)上作為開發(fā)語言。

    Go語言在并發(fā)方面,goroutine和channel機(jī)制提供了輕量級(jí)并發(fā)機(jī)制;在性能方面,與Java的性能不分上下,而內(nèi)存資源消耗方面,相對(duì)Java和其他動(dòng)態(tài)語言,具備明顯的優(yōu)勢(shì)。在網(wǎng)絡(luò)和HTTP應(yīng)用方面,Go語言有良好的標(biāo)準(zhǔn)庫(kù)和生態(tài)系統(tǒng)支持,而在標(biāo)準(zhǔn)庫(kù)方面,已提供了處理多種網(wǎng)絡(luò)所需的輕量級(jí)的代碼庫(kù),對(duì)網(wǎng)絡(luò)的核心協(xié)議HTTP的高并發(fā)支持,完全可以撼動(dòng)Java。國(guó)產(chǎn)處理器由于指令集及工藝等多方面原因,導(dǎo)致單核計(jì)算性能不高,為提高整體計(jì)算能力均采用多核技術(shù)。如:龍芯3B1500為8核,商用服務(wù)器為雙路16核(2顆3B1500),飛騰FT1500A服務(wù)器為16核。因此,充分利用多核計(jì)算能力或搭建基于國(guó)產(chǎn)處理器的云計(jì)算平臺(tái)是目前國(guó)產(chǎn)化平臺(tái)的提高整體性能發(fā)展的方向。

4 Go語言在國(guó)產(chǎn)環(huán)境下的移植

    以飛騰平臺(tái)為例,飛騰CPU采用ARM64構(gòu)架。首先在X86平臺(tái)上交叉編譯出面向ARM64平臺(tái)的Go語言自舉編譯工具,利用$GOOS=linux GOARCH=arm64./bootstrap.bash 編譯命令編譯出可在ARM64平臺(tái)運(yùn)行的Go語言自舉編譯工具,然后利用該自舉編譯工具在ARM64平臺(tái)編譯安裝Go源碼。安裝完成后,Go語言會(huì)自動(dòng)進(jìn)行自身測(cè)試。測(cè)試完成后提示ALL TESTS PASSED,添加GOROOT至系統(tǒng)環(huán)境變量。Go語言的移植完成。龍芯平臺(tái)移植過程與飛騰平臺(tái)移植過程不同之處是在編譯自舉工具時(shí)GOARCH參數(shù)設(shè)置為MIPS64le。

5 Go語言的多核工作原理簡(jiǎn)介

    Go語言可以快速高效地調(diào)用多核進(jìn)行計(jì)算,其優(yōu)勢(shì)源于Go語言的Go runtime的調(diào)度器[2]。

    用戶空間線程和內(nèi)核空間線程之間的映射關(guān)系有N:1、1:1和M:N 3種通常的線程模型。其中N:1模型是幾個(gè)用戶空間線程在一個(gè)OS線程上運(yùn)行。該模型上下文切換非??焖?,但不能利用多核系統(tǒng)的優(yōu)點(diǎn)。1:1模型一個(gè)執(zhí)行線程匹配一個(gè)OS線程。 它利用機(jī)器上的所有內(nèi)核,但上下文切換速度較慢,因?yàn)樗仨毻ㄟ^操作系統(tǒng)進(jìn)行。

    Go通過使用M:N調(diào)度程序來取得上述兩種方式的最佳效果。它將任意數(shù)量的goroutine調(diào)度到任意數(shù)量的OS線程上。開發(fā)者可以獲得快速上下文切換,并利用系統(tǒng)中的所有內(nèi)核。這種方法的主要缺點(diǎn)是增加了調(diào)度器的復(fù)雜性。

    為了完成調(diào)度任務(wù),Go Scheduler使用3個(gè)主要實(shí)體,如圖1所示。

zs1-t1.gif

    M三角形表示OS線程。這是由操作系統(tǒng)管理的執(zhí)行線程,其工作原理與標(biāo)準(zhǔn)POSIX線程相似。

    G圓圈代表一個(gè)goroutine。它包括堆棧、指令指針和其他重要的調(diào)度goroutines的信息,像任何可能被阻止的channel等。

    P是從N:1調(diào)度程序進(jìn)入M:N調(diào)度程序的重要部分,表示調(diào)度的上下文。可以將其視為在單個(gè)線程上運(yùn)行Go代碼的調(diào)度程序,一個(gè)局部的調(diào)度器。

    如圖2所示,有2個(gè)線程(M),每個(gè)線程都有一個(gè)上下文(P),每個(gè)線程都運(yùn)行一個(gè)goroutine(G)。為了運(yùn)行g(shù)oroutines,線程必須持有一個(gè)上下文。

zs1-t2.gif

    P的數(shù)量可以通過GOMAXPROCS()來設(shè)置,代表了真正的并發(fā)度,即有多少個(gè)goroutine可以同時(shí)運(yùn)行。可以使用它來調(diào)整Go進(jìn)程到計(jì)算機(jī)的調(diào)用,例如在4核心PC上運(yùn)行4個(gè)線程的Go代碼。

    白色的goroutines沒有運(yùn)行,處于就緒狀態(tài),正在等待被調(diào)度。P維護(hù)著這個(gè)隊(duì)列。在Go語言里,每當(dāng)goroutine執(zhí)行g(shù)o語句時(shí),goroutines都會(huì)添加到隊(duì)列的末尾。一旦上下文運(yùn)行了一個(gè)goroutine直到調(diào)度點(diǎn),它會(huì)從其運(yùn)行隊(duì)列中彈出一個(gè)goroutine,設(shè)置堆棧和指令指針,并開始運(yùn)行g(shù)oroutine。

    圖3中當(dāng)一個(gè)OS線程被阻塞時(shí),P可以轉(zhuǎn)而投奔另一個(gè)系統(tǒng)線程。從圖中看到,當(dāng)一個(gè)線程M0陷入阻塞時(shí),P轉(zhuǎn)而在OS線程M1上運(yùn)行。調(diào)度器保證有足夠的線程來運(yùn)行所有P。

zs1-t3.gif

    M1可能是被創(chuàng)建,或者從線程緩存中取出。當(dāng)syscall返回時(shí),它必須嘗試獲取一個(gè)上下文來運(yùn)行返回的goroutine,一般情況下,它會(huì)從其他的系統(tǒng)線程取得一個(gè)上下文,如果沒有獲取到,它就把goroutine放在一個(gè)全局隊(duì)列中,放入線程緩存里。上下文會(huì)周期性地檢查全局隊(duì)列,否則全局隊(duì)列上的goroutine永遠(yuǎn)無法執(zhí)行。

    如果上下文的運(yùn)行隊(duì)列的工作量不平衡,如圖4所示,則可能會(huì)發(fā)生這種情況。P所分配的任務(wù)G很快就執(zhí)行完了(分配不均),這就導(dǎo)致了一個(gè)上下文P空閑而系統(tǒng)忙碌。當(dāng)一個(gè)上下文用完時(shí),它將嘗試從另一個(gè)上下文中竊取大約一半的運(yùn)行隊(duì)列。這確保在每個(gè)上下文上總是有工作要做,這反過來確保所有線程都以最大容量工作,每個(gè)系統(tǒng)線程都能充分地使用。

zs1-t4.gif

6 實(shí)測(cè)Go語言在國(guó)產(chǎn)平臺(tái)的多核調(diào)用

6.1 并行積分計(jì)算原理

    并行計(jì)算積分。計(jì)算積分是一個(gè)用來展示并發(fā)編程和它本身加速度(表示的是多處理器執(zhí)行時(shí)間和單處理器執(zhí)行時(shí)間的比值)的常見例子,例如一個(gè)函數(shù)f(x)在[a,b]上的積分:

zs1-gs1-4.gif

    通過循環(huán)觸發(fā)goroutine(協(xié)程)來實(shí)現(xiàn)np個(gè)子算組的并行運(yùn)算,通過Go代碼來計(jì)算Pi的積分:

    zs1-gs5.gif

6.2 Go語言并行計(jì)算核心代碼實(shí)現(xiàn)

    核心代碼:

zs1-6.2-x1.gif

    上述計(jì)算中,一個(gè)計(jì)算組是通過 block(start,end int,c chan float64)這個(gè)函數(shù)實(shí)現(xiàn)的,這個(gè)函數(shù)計(jì)算從start到end之間的矩形面積、通道(channl)c則是用來在結(jié)束的時(shí)候進(jìn)行同步,并且把計(jì)算組的結(jié)果送到主線程。主線程通過調(diào)用rutime.GOMAXPROCS(np)建立運(yùn)行時(shí)所使用的CPU核數(shù),np為使用CPU的個(gè)數(shù),然后通過make構(gòu)造一個(gè)有np大小緩存的通道,進(jìn)行阻塞,確保計(jì)算并行進(jìn)行。最后把執(zhí)行np次的結(jié)果進(jìn)行累加以獲得pi的結(jié)果。

6.3 Go語言并行計(jì)算在國(guó)產(chǎn)CPU多核調(diào)用測(cè)試

6.3.1 測(cè)試環(huán)境

    飛騰平臺(tái):FT1500A16核×1;內(nèi)存16 GB;Go編譯器1.8.1;操作系統(tǒng):銀河麒麟4.0。

    龍芯平臺(tái):3B1500A8核×2;內(nèi)存16 GB;Go編譯器1.8.1;操作系統(tǒng):中標(biāo)麒麟6.0。

6.3.2 測(cè)試方法

    程序內(nèi)計(jì)時(shí),每次測(cè)試3次,取最短時(shí)間。結(jié)果如圖5、圖6所示。

zs1-t5.gif

zs1-t6.gif

    上面兩組數(shù)據(jù)圖展示了,在龍芯3B1500處理器和飛騰FT1500A上,并行Go計(jì)算Pi的效率,對(duì)于小的問題規(guī)模(n=105,106),使用多核不能增加的執(zhí)行時(shí)間,這是因?yàn)檫^多的進(jìn)程調(diào)度和初始化協(xié)程導(dǎo)致的,大部分時(shí)間沒有執(zhí)行并行計(jì)算。當(dāng)問題規(guī)模n變大的時(shí)候(n=108,109,1010),使用多處理器能夠顯著地縮短計(jì)算所需的執(zhí)行時(shí)間。

6.3.3 結(jié)果對(duì)比

    結(jié)果對(duì)比如圖7所示。

zs1-t7.gif

    從圖7可以看出,與其他公開的測(cè)試的數(shù)據(jù)基本一致,飛騰FT1500A無論單核和多核性能均比龍芯3B1500CPU計(jì)算能力快出近一倍。

6.4 Go語言在調(diào)用多核進(jìn)行并行計(jì)算的性能線性特性

    為了能夠體現(xiàn)并發(fā)執(zhí)行的加速度,以飛騰F1500A為例子以通過式(6)計(jì)算速度:

    zs1-gs6.gif

    在這里Tnp和TMaxnp是處理器當(dāng)前使用核數(shù)計(jì)算所用時(shí)間和處理器最大核數(shù)計(jì)算所用時(shí)間。結(jié)果如圖8所示。

zs1-t8.gif

    在圖8中,當(dāng)問題規(guī)模非常大的時(shí)候,增長(zhǎng)幾乎就是線性的了,特別是問題規(guī)模達(dá)到(n=109)的時(shí)候,幾乎和擬合趨勢(shì)線重合。

7 結(jié)束語

    本文對(duì)Go語言在多線程領(lǐng)域編程、跨異構(gòu)平臺(tái)及編程難易程度的優(yōu)勢(shì)進(jìn)行了闡述;對(duì)目前我國(guó)國(guó)產(chǎn)CPU在商業(yè)化應(yīng)用領(lǐng)域現(xiàn)狀進(jìn)行了分析。使用Go語言在主流兩款國(guó)產(chǎn)平臺(tái)對(duì)多核調(diào)用進(jìn)行測(cè)試。同時(shí),對(duì)Go語言的多核工作原理進(jìn)行了簡(jiǎn)要分析。綜上所述,Go語言非常適合作為除Java外的另一種國(guó)產(chǎn)CPU平臺(tái)應(yīng)用開發(fā)語言,有較為廣泛的應(yīng)用前景。本文對(duì)未來Go語言在國(guó)產(chǎn)CPU平臺(tái)上的開發(fā)及應(yīng)用提供了一定的參考價(jià)值。

參考文獻(xiàn)

[1] 芮雪,王亮亮,楊琴.國(guó)產(chǎn)處理器研究與發(fā)展現(xiàn)狀綜述[J].現(xiàn)代計(jì)算機(jī)(普及版),.2014(3):15-19.

[2] MORSING D.The Go scheduler[Z].2013.




作者信息:

陳  希,胡  彬

(國(guó)家工業(yè)信息安全發(fā)展研究中心,北京100040)

此內(nèi)容為AET網(wǎng)站原創(chuàng),未經(jīng)授權(quán)禁止轉(zhuǎn)載。