唐劍寅,肖炳甲,袁旗平
1(中國(guó)科學(xué)院 合肥物質(zhì)科學(xué)研究院 等離子體物理研究所,合肥 230031)
2(中國(guó)科學(xué)技術(shù)大學(xué),合肥 230026)
EAST (Experimental Advanced Superconductive Tokamak)是我國(guó)自行設(shè)計(jì)研制的全超導(dǎo)托卡馬克裝置,目前進(jìn)行周期100 μs,總時(shí)長(zhǎng)最長(zhǎng)1000 s的放電實(shí)驗(yàn).其等離子體控制系統(tǒng)PCS (Plasma Control System)負(fù)責(zé)從外部子系統(tǒng)獲取數(shù)據(jù)并運(yùn)行控制算法,最終將結(jié)果反饋到外部系統(tǒng).
EAST PCS在硬件平臺(tái)上,使用x86 Linux服務(wù)器作為控制進(jìn)程執(zhí)行環(huán)境,外部設(shè)備則使用不依賴中斷工作的輪詢?cè)O(shè)備,包括采集卡和反射內(nèi)存卡.系統(tǒng)方面使用定制的2.6內(nèi)核Linux,該系統(tǒng)主要通過(guò)模塊方式增加了一個(gè)屏蔽外部設(shè)備中斷的接口,供控制進(jìn)程調(diào)用[1].
較短的放電周期給系統(tǒng)實(shí)時(shí)性提出一定要求,PCS中控制進(jìn)程選擇采用循環(huán)輪詢(Polled Loop)方式運(yùn)行[2],相較于中斷事件驅(qū)動(dòng)型程序,這種方式采用循環(huán)等待的方式獲取資源,持續(xù)持有CPU,而非頻繁進(jìn)入中斷,在PCS這類數(shù)據(jù)量大、計(jì)算任務(wù)重的快速系統(tǒng)中能獲得更穩(wěn)定的實(shí)時(shí)能力.在放電執(zhí)行階段,根據(jù)算法不同,多個(gè)相應(yīng)控制進(jìn)程進(jìn)入實(shí)時(shí)控制狀態(tài)并行運(yùn)行,簡(jiǎn)單示例如圖1,控制進(jìn)程在獲取數(shù)據(jù)時(shí),循環(huán)讀取共享內(nèi)存或反射內(nèi)存卡以等待數(shù)據(jù)到來(lái); 進(jìn)行延時(shí)操作時(shí),循環(huán)讀取TSC (Time Stamp Counter)得到當(dāng)前時(shí)間,直到超時(shí).
圖1 控制進(jìn)程工作方式示例
控制進(jìn)程還進(jìn)行了CPU親和性設(shè)置,總是運(yùn)行在特定處理器核上不發(fā)生遷移.并且采用了mlockall的方式鎖定內(nèi)存,避免在運(yùn)行過(guò)程中發(fā)生內(nèi)存缺頁(yè),進(jìn)行處理時(shí)延誤控制進(jìn)程運(yùn)行.
循環(huán)輪詢進(jìn)程期望獲得所有處理器時(shí)間,但Linux內(nèi)核無(wú)法保證某個(gè)任務(wù)不受干擾地持續(xù)運(yùn)行,系統(tǒng)噪聲成為了PCS控制進(jìn)程的瓶頸.Linux系統(tǒng)噪聲的產(chǎn)生是由于系統(tǒng)本身為了維持正常運(yùn)行,偶爾需要占用處理器一段時(shí)間,在進(jìn)程中就表現(xiàn)為延遲[3].從系統(tǒng)層面而言,控制進(jìn)程產(chǎn)生延遲的直接原因,無(wú)非是其它進(jìn)程或中斷占用處理器[4].在當(dāng)前100 μs控制周期下,這些延遲壓縮了控制進(jìn)程數(shù)據(jù)采集、計(jì)算和傳輸?shù)目捎脮r(shí)間,甚至導(dǎo)致控制進(jìn)程周期內(nèi)無(wú)法完成工作,影響控制效果.而PCS還計(jì)劃采用50 μs周期控制周期,這一需求又將進(jìn)一步放大噪聲影響.
EAST PCS和韓國(guó)KSTAR PCS都源自美國(guó)的DIII-D PCS,三者有著類似的軟硬件特性.
DIII-D PCS目前采用CentOS 6系統(tǒng),內(nèi)核為2.6.32.為減少系統(tǒng)噪聲,DIII-D PCS使用了isolcpus內(nèi)核啟動(dòng)參數(shù)以避免系統(tǒng)自動(dòng)分配任務(wù)至控制進(jìn)程所在處理器,并設(shè)置了設(shè)備中斷親和性,以避免設(shè)備中斷干擾.
KSTAR PCS目前采用Scientific Linux 6系統(tǒng)和CERN MRG實(shí)時(shí)內(nèi)核,內(nèi)核版本為3.10.33,其采用實(shí)時(shí)內(nèi)核主要因?yàn)槭褂昧水a(chǎn)生中斷的設(shè)備[5].KSTAR PCS中的控制進(jìn)程采用了實(shí)時(shí)調(diào)度以避免控制進(jìn)程被意外調(diào)度,并且同樣使用了內(nèi)核啟動(dòng)參數(shù)isolcpus.
二者對(duì)于EAST PCS進(jìn)行系統(tǒng)噪聲改善有一定借鑒意義,尤其是實(shí)時(shí)優(yōu)先級(jí)的加入和設(shè)備中斷遷移的做法值得應(yīng)用.然而EAST的控制周期更短,實(shí)驗(yàn)時(shí)間更長(zhǎng),并且三個(gè)PCS的控制進(jìn)程也互有區(qū)別.EAST PCS若武斷提升控制進(jìn)程為實(shí)時(shí)優(yōu)先級(jí)容易導(dǎo)致進(jìn)程阻塞等問(wèn)題,并且僅僅禁止調(diào)度可能仍無(wú)法滿足控制需求.
為控制進(jìn)程添加實(shí)時(shí)優(yōu)先級(jí)并設(shè)法減少中斷發(fā)生是減少系統(tǒng)噪聲的基本思路,本文通過(guò)在PCS代碼中選擇恰當(dāng)時(shí)機(jī)設(shè)置實(shí)時(shí)優(yōu)先級(jí),并進(jìn)行相應(yīng)系統(tǒng)調(diào)整,避免可能出現(xiàn)進(jìn)程或系統(tǒng)阻塞問(wèn)題,另外本文還通過(guò)遷移設(shè)備中斷、使用無(wú)滴答內(nèi)核讓中斷發(fā)生情況得到大幅改觀,最終通過(guò)對(duì)比測(cè)試,證明了本文方法切實(shí)有效.
EAST PCS控制進(jìn)程未特別指定調(diào)度方式,其所在核上運(yùn)行隊(duì)列中的進(jìn)程可能帶來(lái)影響.運(yùn)行隊(duì)列中的進(jìn)程一般來(lái)自兩種情況:
(1) 內(nèi)核為了保證系統(tǒng)負(fù)載均衡,會(huì)將進(jìn)程分配到各個(gè)處理器核上;
(2) 內(nèi)核在各個(gè)核會(huì)固定維持一些守護(hù)進(jìn)程,并且不時(shí)喚醒.
由于Linux中的完全公平調(diào)度器CFS (Completely Fair Scheduler)趨向于為運(yùn)行隊(duì)列中進(jìn)程公平分配CPU時(shí)間[6],這兩種進(jìn)程都可能導(dǎo)致控制進(jìn)程產(chǎn)生被動(dòng)上下文切換(involuntary context switch),從而存在延遲.
使用實(shí)時(shí)調(diào)度方式能減少控制進(jìn)程受到的無(wú)關(guān)進(jìn)程影響,Linux內(nèi)核一般至少提供SCHED_FIFO和SCHED_RR兩種實(shí)時(shí)調(diào)度方式.采用這兩種調(diào)度方式的任務(wù)能比普通任務(wù)優(yōu)先執(zhí)行,并且高優(yōu)先級(jí)實(shí)時(shí)任務(wù)總是能夠搶占低優(yōu)先級(jí)實(shí)時(shí)任務(wù).對(duì)于同一優(yōu)先級(jí)的任務(wù),采用SCHED_RR方式的任務(wù)會(huì)和其它任務(wù)輪流運(yùn)行,而采用SCHED_FIFO的任務(wù)采用先進(jìn)先出的方式運(yùn)行,直到任務(wù)完全結(jié)束或者主動(dòng)放棄CPU,才會(huì)允許下一個(gè)任務(wù)投入運(yùn)行[7].
在Linux系統(tǒng)中,中斷永遠(yuǎn)比進(jìn)程優(yōu)先被處理,因此實(shí)時(shí)優(yōu)先級(jí)無(wú)法避免中斷帶來(lái)的延遲.
由于外部設(shè)備中斷被屏蔽,目前EAST PCS中發(fā)生最為頻繁的是本地時(shí)鐘中斷LOC (Local timer interrupt).系統(tǒng)利用LOC中斷進(jìn)行狀態(tài)更新、信息統(tǒng)計(jì)、內(nèi)存回收、任務(wù)調(diào)度等工作[8].LOC中斷的頻率取決于內(nèi)核編譯時(shí)CONFIG_HZ的值,在EAST PCS Linux系統(tǒng)中 LOC中斷頻率默認(rèn)為1000 HZ.
自3.10內(nèi)核以后,Linux支持完全動(dòng)態(tài)滴答特性(Full Dynamic ticks),即當(dāng)前核上的運(yùn)行隊(duì)列中不超過(guò)1個(gè)任務(wù)時(shí),將CPU的LOC中斷設(shè)置為1 Hz[9],該特性大大降低了中斷頻率.在一些看重延遲或吞吐量的高性能計(jì)算場(chǎng)景中,該特性一般會(huì)被應(yīng)用,以減少系統(tǒng)噪聲,獲得更穩(wěn)定的性能[10].
完全動(dòng)態(tài)滴答特性開(kāi)啟后,仍會(huì)保持1 Hz的時(shí)鐘中斷滴答,用于更新vruntime、負(fù)載信息等,低精度定時(shí)任務(wù)也依賴該滴答.由于EAST PCS專用于控制,對(duì)調(diào)度的和負(fù)載信息統(tǒng)計(jì)的準(zhǔn)確性及時(shí)性并不要求,因此可將1 Hz的時(shí)鐘滴答完全消除以進(jìn)一步減少控制進(jìn)程抖動(dòng).
PCS采用SCHED_FIFO調(diào)度和最高實(shí)時(shí)優(yōu)先級(jí)調(diào)度控制進(jìn)程,以完全避免控制過(guò)程中進(jìn)程切換.
PCS代碼中添加實(shí)時(shí)調(diào)度的時(shí)機(jī)有所選擇,主要因?yàn)閮?nèi)核對(duì)mlockall的實(shí)現(xiàn),與PCS控制進(jìn)程采用的循環(huán)輪詢方式存在沖突.Linux內(nèi)核自2.6.28版本以后,mlockall的實(shí)現(xiàn)中調(diào)用了lru_add_drain_all函數(shù),該函數(shù)負(fù)責(zé)將pagevec中的頁(yè)轉(zhuǎn)移到相應(yīng)lru鏈表中,它將這一工作交給每個(gè)核上的內(nèi)核工作隊(duì)列線程,并等待其執(zhí)行結(jié)束.然而內(nèi)核工作隊(duì)列線程并非實(shí)時(shí)優(yōu)先級(jí),會(huì)被已運(yùn)行的實(shí)時(shí)循環(huán)輪詢進(jìn)程阻塞,從而導(dǎo)致mlockall無(wú)法執(zhí)行結(jié)束.因此在PCS代碼中需保證所有控制進(jìn)程的mlockall執(zhí)行結(jié)束,才能提升任務(wù)為實(shí)時(shí)優(yōu)先級(jí).在PCS中,控制進(jìn)程的工作分為三部分,首先是設(shè)置階段,這一階段控制進(jìn)程預(yù)先申請(qǐng)所需內(nèi)存和其它資源,并且使用mlockall鎖定整個(gè)內(nèi)存; 第二階段是執(zhí)行階段,進(jìn)行等離子體控制; 第三階段是清除階段,進(jìn)行資源釋放和數(shù)據(jù)存儲(chǔ)[11].設(shè)置階段所有控制進(jìn)程都會(huì)完成初始化,mlockall也在初始化階段調(diào)用,完成設(shè)置的進(jìn)程進(jìn)入輪詢狀態(tài)等待執(zhí)行階段開(kāi)始.若控制進(jìn)程直接以實(shí)時(shí)優(yōu)先級(jí)運(yùn)行,最快完成內(nèi)存鎖定的進(jìn)程會(huì)以實(shí)時(shí)優(yōu)先級(jí)持續(xù)持有CPU,其它進(jìn)程的內(nèi)存鎖定工作便因此阻塞.因此實(shí)時(shí)優(yōu)先級(jí)的設(shè)置應(yīng)當(dāng)在初始化階段之后,進(jìn)入執(zhí)行狀態(tài)之前,才能保障進(jìn)程不發(fā)生阻塞.
EAST PCS控制進(jìn)程采用實(shí)時(shí)優(yōu)先級(jí)后,成為實(shí)時(shí)循環(huán)輪詢進(jìn)程,并在運(yùn)行時(shí)希望獲得全部的CPU時(shí)間.而內(nèi)核的默認(rèn)配置并不保證這點(diǎn),內(nèi)核對(duì)實(shí)時(shí)進(jìn)程的運(yùn)行時(shí)間進(jìn)行了限制,讓每秒中有部分時(shí)間用于普通進(jìn)程.以下命令可以解除該限制[12]: echo-1 > /proc/sys/kernel/sched_rt_runtime_us
控制進(jìn)程提升至實(shí)時(shí)優(yōu)先級(jí)后,相應(yīng)核上其它進(jìn)程得不到運(yùn)行,這可能導(dǎo)致系統(tǒng)無(wú)法正常工作.在3.10內(nèi)核中,還需進(jìn)行如下配置:
(1) 避免系統(tǒng)自動(dòng)分配進(jìn)程到相應(yīng)核上.在內(nèi)核啟動(dòng)參數(shù)中添加”isolcpus=1–N”,N的值為處理器核數(shù)減一.這里僅保留第0個(gè)處理器核為守護(hù)核,接管非控制任務(wù).
(2) 避免系統(tǒng)喚醒控制進(jìn)程核上的守護(hù)進(jìn)程.系統(tǒng)會(huì)喚醒守護(hù)進(jìn)程執(zhí)行日常事務(wù)活動(dòng)[13],一些工作具有NUMA親和性,可能導(dǎo)致工作無(wú)意識(shí)地分配在非守護(hù)核上而被阻塞.在內(nèi)核啟動(dòng)參數(shù)中添加”numa=off”,以避免該情況.I/O可能在不同核上喚醒處理,通過(guò)以下命令進(jìn)行設(shè)置,避免I/O隊(duì)列放到非守護(hù)核: echo 1 > /sys/bus/workqueue/devices/writeback/cpumask.
(3) 關(guān)閉系統(tǒng)檢測(cè)機(jī)制.由于放電實(shí)驗(yàn)最長(zhǎng)可至1000 s,控制進(jìn)程在此期間不放棄處理器,如此長(zhǎng)的時(shí)間會(huì)讓Linux系統(tǒng)中watchdog判斷系統(tǒng)掛起.使用如下命令關(guān)閉watchdog:
echo 0 > /proc/sys/kernel/watchdog
echo 0 > /proc/sys/kernel/nmi_watchdog
PCS升級(jí)內(nèi)核至3.10版本以獲得完全動(dòng)態(tài)滴答特性,并更改了對(duì)外部設(shè)備中斷的處理方式.
外部設(shè)備中斷在Linux中/proc文件系統(tǒng)中分配了一個(gè)數(shù)字中斷號(hào),可以通過(guò)/proc接口設(shè)置中斷對(duì)CPU的親和性,從而實(shí)現(xiàn)中斷遷移.更新內(nèi)核后,PCS選擇將外部設(shè)備中斷遷移到守護(hù)核,而非直接屏蔽設(shè)備中斷,因此在放電實(shí)驗(yàn)執(zhí)行階段,控制進(jìn)程所在服務(wù)器仍具備通過(guò)網(wǎng)絡(luò)遠(yuǎn)程管理的能力.
為了進(jìn)一步提供不受中斷影響的環(huán)境,PCS中基于Linux 3.10內(nèi)核已有的完全動(dòng)態(tài)滴答特性,為內(nèi)核添加了新的啟動(dòng)參數(shù)pcs_nohz.設(shè)置該參數(shù)后,LOC中斷頻率從1 Hz變成0 Hz,從而LOC中斷次數(shù)不再隨放電實(shí)驗(yàn)時(shí)間增長(zhǎng)而增加.
以3.10內(nèi)核源代碼為例,具體修改方式如下:
(2) 在scheduler_tick_max_deferment函數(shù)中添加兩行新代碼, 修改后的函數(shù)如下:
然后確保配置CONFIG_NO_HZ_FULL=y并編譯安裝內(nèi)核,在內(nèi)核啟動(dòng)參數(shù)中添加”nohz_full=1-N pcsnohz”并重啟,即可消除時(shí)鐘滴答.
PCS系統(tǒng)中直接使用匯編指令rdtsc讀取TSC來(lái)計(jì)時(shí),使用該指令讀取時(shí)間至局部變量中僅耗費(fèi)數(shù)十個(gè)指令周期,而系統(tǒng)的噪聲導(dǎo)致延遲的間隔一般遠(yuǎn)大于此開(kāi)銷.因此可以使用連續(xù)的rdtsc指令得到延遲數(shù)據(jù),并從次數(shù)和大小兩個(gè)維度進(jìn)行統(tǒng)計(jì).
測(cè)試平臺(tái)配置如表1所示.
表1 測(cè)試平臺(tái)配置
測(cè)試運(yùn)行時(shí)間選擇1000 s,這是目前等離子體放電的最長(zhǎng)時(shí)間,同時(shí),有的中斷周期或者系統(tǒng)檢測(cè)機(jī)制周期可能長(zhǎng)達(dá)數(shù)百秒,1000 s一般足夠涵蓋所有可能的系統(tǒng)噪聲類型.
測(cè)試的內(nèi)核有三個(gè)版本,分別為:
1) 2.6.32,維持PCS原來(lái)的系統(tǒng)配置和調(diào)度方式(屏蔽外部設(shè)備中斷,使用CFS調(diào)度),控制進(jìn)程的原本運(yùn)行環(huán)境;
2) 3.10,屏蔽外部設(shè)備中斷,使用CFS調(diào)度,模擬PCS直接升級(jí)內(nèi)核的表現(xiàn);
3) 3.10,采用實(shí)時(shí)調(diào)度,使用改善過(guò)中斷的內(nèi)核,優(yōu)化延遲后的控制進(jìn)程運(yùn)行環(huán)境.
PCS中可以忽略1 μs以下的延遲,在測(cè)試平臺(tái)上,使用連續(xù)讀取TSC的方式,測(cè)試1000 s,僅統(tǒng)計(jì)1 μs及以上延遲,得到結(jié)果如圖2.
從圖2中可以發(fā)現(xiàn),2.6.32內(nèi)核大部分延遲分布在[1,2) μs區(qū)間,隨著延遲增大,延遲發(fā)生次數(shù)逐步減少,但超過(guò)5 μs的延遲仍有相當(dāng)一部分.使用3.10內(nèi)核比2.6.32內(nèi)核單次延遲時(shí)間出現(xiàn)增長(zhǎng),這是由于Linux在各個(gè)版本中,內(nèi)核代碼變動(dòng)較多,導(dǎo)致系統(tǒng)噪聲帶來(lái)的延遲并不一致,并非越新的內(nèi)核就能帶來(lái)更佳效果.而按照本文的延遲優(yōu)化方法,在3.10內(nèi)核上,只發(fā)生3次延遲,并且所有延遲都在5 μs以內(nèi),改善十分顯著.
不進(jìn)行延遲優(yōu)化時(shí),表2中≥1 μs總延遲次數(shù)在使用2.6.32和3.10內(nèi)核時(shí)是類似的,結(jié)合1000 Hz的LOC中斷頻率,可以發(fā)現(xiàn)總延遲次數(shù)剛好和LOC中斷次數(shù)接近,這也凸顯LOC中斷對(duì)系統(tǒng)整體延遲的影響.不應(yīng)用優(yōu)化策略情況下,延遲最大值已經(jīng)突破了100 μs控制周期的限制,對(duì)控制效果必然產(chǎn)生影響.
經(jīng)過(guò)優(yōu)化,控制進(jìn)程的實(shí)時(shí)優(yōu)先級(jí)保證其在執(zhí)行階段不會(huì)發(fā)生被動(dòng)上下文切換,并且無(wú)滴答的內(nèi)核不再有每秒固定次數(shù)的LOC中斷打擾控制進(jìn)程,這是測(cè)試結(jié)果中優(yōu)化前后出現(xiàn)差異的主要原因.優(yōu)化前后結(jié)果對(duì)比顯示本文方法能夠大幅減少延遲頻率,并且改善最壞延遲情況.PCS控制進(jìn)程并非每周期中所有時(shí)間都在進(jìn)行運(yùn)算和數(shù)據(jù)傳輸,而是一部分時(shí)間用于標(biāo)志位輪詢,這部分時(shí)間是彈性的.這實(shí)際增加了PCS對(duì)于系統(tǒng)噪聲的容忍度,只有系統(tǒng)噪聲過(guò)大或者發(fā)生在周期末尾才會(huì)導(dǎo)致周期超出.而優(yōu)化后即使最壞情況發(fā)生,單個(gè)PCS控制進(jìn)程僅僅超出周期3 μs,幾乎不對(duì)等離子體控制產(chǎn)生影響.
圖2 測(cè)試1000 s延遲分布情況
表2 測(cè)試1000 s延遲總體情況
系統(tǒng)噪聲通常直接來(lái)自調(diào)度和中斷,會(huì)給PCS控制進(jìn)程的執(zhí)行帶來(lái)延遲,本文按照增加實(shí)時(shí)調(diào)度,降低中斷頻率的基本思路來(lái)改善控制進(jìn)程延遲.
加入實(shí)時(shí)調(diào)度方式需要協(xié)調(diào)好實(shí)時(shí)優(yōu)先級(jí)與已有代碼的關(guān)系,合理安排控制進(jìn)程提升為實(shí)時(shí)任務(wù)的時(shí)機(jī).同時(shí)還需調(diào)整系統(tǒng),使之與長(zhǎng)時(shí)間實(shí)時(shí)循環(huán)輪詢?nèi)蝿?wù)不沖突.
中斷的減少有多種優(yōu)化方式,對(duì)外部設(shè)備中斷這類能夠直接遷移的中斷只需進(jìn)行一些系統(tǒng)配置,而對(duì)LOC中斷則需通過(guò)修改內(nèi)核代碼降低其發(fā)生頻率.
優(yōu)化后的測(cè)試結(jié)果顯示,進(jìn)程能感知到的最大延遲下降到3 μs左右,同時(shí)延遲次數(shù)極低.經(jīng)過(guò)分析,該結(jié)果已完全符合等離子體控制需求.
在循環(huán)輪詢進(jìn)程的實(shí)時(shí)性方面,本文已做到基本消除系統(tǒng)噪聲,但未來(lái)等離子體控制必然使用更高速的外部設(shè)備,其中一些設(shè)備可能依賴中斷工作.那時(shí)使用一款實(shí)時(shí)操作系統(tǒng),并進(jìn)一步改善中斷響應(yīng)和進(jìn)程喚醒的實(shí)時(shí)性,又將成為新的挑戰(zhàn).