本文講述一些有利于提高xenomai實(shí)時(shí)性的配置建議,部分針對(duì)X86架構(gòu),但它們的底層原理相通,同樣適用于其他CPU架構(gòu)和系統(tǒng),希望對(duì)你有用。
一、前言
1. 什么是實(shí)時(shí)
“實(shí)時(shí)”一詞在許多應(yīng)用領(lǐng)域中使用,人們它有不同的解釋,并不總是正確的。人們常說(shuō),如果控制系統(tǒng)能夠?qū)ν獠渴录龀隹焖俜磻?yīng),那么它就是實(shí)時(shí)運(yùn)行的。根據(jù)這種解釋,如果系統(tǒng)速度快,則系統(tǒng)被認(rèn)為是實(shí)時(shí)的。然而,“快”具有相對(duì)含義,并未涵蓋表征這些類型系統(tǒng)的主要屬性。
我們來(lái)看一下,在自然界中,生物在棲息地中的實(shí)時(shí)行為,這些行為與它們的速度無(wú)關(guān)。例如,烏龜對(duì)來(lái)自其棲息地的外部刺激的反應(yīng),與貓對(duì)其棲息地的外部反應(yīng)一樣有效。雖然烏龜比貓慢很多,但就絕對(duì)速度而言,它要處理的事件與它可以協(xié)調(diào)的動(dòng)作成正比,這是任何動(dòng)物在環(huán)境中生存的必要條件。
相反,如果生物系統(tǒng)所處的環(huán)境,引入了速度超過(guò)其處理能力的事件,其行為將不再有效,動(dòng)物的生存也會(huì)受到損害。比如,一只蒼蠅可以被蒼蠅拍捕捉到,一只老鼠可以被陷阱捕捉到,或者一只貓可以被高速行駛的汽車撞倒。在這些例子中,蒼蠅拍、陷阱和汽車代表了動(dòng)物的異常和異常事件,超出了它們的實(shí)時(shí)能力范圍,可能嚴(yán)重危及它們的生存。
前面的例子表明,實(shí)時(shí)并沒(méi)有人們想象的那樣快,而是與系統(tǒng)運(yùn)行的環(huán)境嚴(yán)格相關(guān)。
實(shí)時(shí)系統(tǒng)是必須在設(shè)置的截止時(shí)間內(nèi)對(duì)環(huán)境中的事件做出反應(yīng)的系統(tǒng),否則會(huì)產(chǎn)生嚴(yán)重的后果。
再比如,船舶的制導(dǎo)系統(tǒng)可能看起來(lái)是一個(gè)非實(shí)時(shí)系統(tǒng),因?yàn)樗乃俣群艿停彝ǔS小白銐颉钡臅r(shí)間(大約幾分鐘)來(lái)做出控制決定。盡管如此,根據(jù)我們的定義,它實(shí)際上是一個(gè)實(shí)時(shí)系統(tǒng)。
2. 實(shí)時(shí)分類
根據(jù)錯(cuò)過(guò)截止時(shí)間產(chǎn)生的后果,實(shí)時(shí)任務(wù)可以分為三類:
硬實(shí)時(shí)(Hard real time system)
如果在截止時(shí)間之后產(chǎn)生結(jié)果,可能對(duì)受控系統(tǒng)造成災(zāi)難性后果,則該任務(wù)是硬實(shí)時(shí)任務(wù)。
硬任務(wù)的例子可以在安全關(guān)鍵系統(tǒng)中找到,并且通常與傳感、驅(qū)動(dòng)和控制活動(dòng)有關(guān),例如:
汽車安全氣囊的檢測(cè)與控制;
反導(dǎo)彈系統(tǒng)要求硬實(shí)時(shí)。反導(dǎo)彈系統(tǒng)由一系列硬實(shí)時(shí)任務(wù)組成。反導(dǎo)系統(tǒng)必須首先探測(cè)所有來(lái)襲導(dǎo)彈,正確定位反導(dǎo)炮,然后在導(dǎo)彈來(lái)襲之前將其摧毀。所有這些任務(wù)本質(zhì)上都是硬實(shí)時(shí)的,如果反導(dǎo)彈系統(tǒng)有任何一個(gè)任務(wù)失敗都將無(wú)法成功攔截來(lái)襲導(dǎo)彈。
強(qiáng)實(shí)時(shí)(Firm real time system)
如果在截止日期之后產(chǎn)生結(jié)果對(duì)系統(tǒng)無(wú)用,但不會(huì)造成任何損害,則該任務(wù)是強(qiáng)實(shí)時(shí)任務(wù)。
在網(wǎng)絡(luò)應(yīng)用程序和多媒體系統(tǒng)中找到,在這些系統(tǒng)中,跳過(guò)一個(gè)數(shù)據(jù)包或一個(gè)視頻幀比長(zhǎng)時(shí)間延遲處理更重要。 因此,它們包括以下內(nèi)容:
視頻播放;
音/視頻編解碼中,沒(méi)有在設(shè)置的碼率時(shí)序范圍內(nèi)執(zhí)行完,產(chǎn)生結(jié)果都是無(wú)用的丟棄即可,繼續(xù)下一輪讀取;
在線圖像處理;
軟實(shí)時(shí)(Soft real time system)
如果實(shí)時(shí)任務(wù)在截止日期之后產(chǎn)生結(jié)果仍然對(duì)系統(tǒng)有用,盡管會(huì)導(dǎo)致性能下降,則該任務(wù)是軟實(shí)時(shí)任務(wù)。
軟任務(wù)通常與系統(tǒng)-用戶交互有關(guān),有點(diǎn)延遲什么的并不影響,只是體驗(yàn)稍差點(diǎn)。 因此,它們包括:
用戶界面的命令解釋器;
處理來(lái)自鍵盤的輸入數(shù)據(jù);
在屏幕上顯示消息;
網(wǎng)頁(yè)瀏覽等;
3.常見(jiàn)的RTOS
小型實(shí)時(shí)操作系統(tǒng) UCOS、FreeRTOS、RT-Thread…
大型實(shí)時(shí)操作系統(tǒng) RT linux、VxWorks、QNX、sylixOS…
4. latency和jitter
硬實(shí)時(shí)系統(tǒng)是必須在設(shè)置的截止時(shí)間內(nèi)對(duì)環(huán)境中的事件做出反應(yīng)的系統(tǒng)。硬實(shí)時(shí)操作系統(tǒng)應(yīng)具備的最重要特性之一是確定性、可預(yù)期性。
操作系統(tǒng)的實(shí)時(shí)性能通常用latency或jitter來(lái)表示。事件預(yù)期發(fā)生與實(shí)際發(fā)生的時(shí)間之間的時(shí)間稱為延遲(latency),實(shí)際發(fā)生的最大時(shí)間與最小時(shí)間之間的差值稱為抖動(dòng)(Jitter),兩者均可表示實(shí)時(shí)性。 根據(jù)實(shí)時(shí)性的定義,延遲必須是確定的,不能超過(guò)deadline,否則將會(huì)產(chǎn)生嚴(yán)重的后果。
當(dāng)我們針對(duì)實(shí)時(shí)應(yīng)用場(chǎng)景評(píng)估硬件和實(shí)時(shí)系統(tǒng)時(shí),通常可以簡(jiǎn)化為對(duì)實(shí)時(shí)性能和硬件資源的考量,即對(duì)于一個(gè)應(yīng)用場(chǎng)景,實(shí)時(shí)性滿足的情況下,硬件性能也滿足。
在否決定使用一個(gè)實(shí)時(shí)系統(tǒng)時(shí),需要結(jié)合具體應(yīng)用場(chǎng)景來(lái)評(píng)估該實(shí)時(shí)系統(tǒng)是否符合,若不符合則需要考慮對(duì)現(xiàn)有系統(tǒng)優(yōu)化或者更換方案。
二、實(shí)時(shí)性的影響因素
硬實(shí)時(shí)操作系統(tǒng)應(yīng)具備的最重要特性之一是確定性、可預(yù)測(cè)性,系統(tǒng)應(yīng)該保證滿足所有關(guān)鍵時(shí)序約束。然而,這取決于一系列因素,這些因素涉及硬件的架構(gòu)特征、內(nèi)核中采用的機(jī)制和策略,以及用于實(shí)現(xiàn)應(yīng)用程序的編程語(yǔ)言、軟件設(shè)計(jì)等。
根據(jù)實(shí)時(shí)性定義,計(jì)算機(jī)系統(tǒng)中所有導(dǎo)致程序執(zhí)行時(shí)間不確定的因素,都是實(shí)時(shí)性影響因素。
1.硬件
CPU架構(gòu)
硬件方面,第一個(gè)影響調(diào)度可預(yù)測(cè)性的是處理器本身。處理器的內(nèi)部特性是不確定性的第一個(gè)原因,例如指令預(yù)取、流水線操作、分支預(yù)測(cè)、高速緩存存儲(chǔ)器和直接存儲(chǔ)器訪問(wèn)(DMA)機(jī)制。這些特性雖然改善了處理器的平均性能,但它們引入了非確定性因素,這些因素阻止了對(duì)最壞情況執(zhí)行時(shí)間WCET(Worst-caseExecutionTime)的精確估計(jì)。
高端CPU,如I5、I7實(shí)時(shí)性不一定有低端的賽揚(yáng)、atom系列的好,芯片的設(shè)計(jì)本身定位就是高吞吐量而不是實(shí)時(shí)性,實(shí)時(shí)性與吞吐量不可兼得。
Cache
CPU 里的 L1 Cache 或者 L2 Cache,訪問(wèn)延時(shí)是內(nèi)存的 1/15 乃至 1/100,想要追求極限性能,需要盡可能地多從 CPU Cache 里面拿數(shù)據(jù),減少cache miss,上面的分配CPU專門對(duì)實(shí)時(shí)任務(wù)服務(wù)就是對(duì)非共享的L1 、L2 Cache的充分優(yōu)化。
對(duì)于L3 Cache,多個(gè)cpu核與GPU共享,無(wú)法避免非實(shí)時(shí)任務(wù)及GUI爭(zhēng)搶L3 Cache對(duì)實(shí)時(shí)任務(wù)的影響。
為此intel 推出了資源調(diào)配技術(shù)(Intel RDT),提供了兩種能力:監(jiān)控和分配。Intel RDT提供了一系列分配(資源控制)能力,包括緩存分配技術(shù)(Cache Allocation Technology, CAT),代碼和數(shù)據(jù)優(yōu)先級(jí)(Code and Data Prioritization, CDP) 以及 內(nèi)存帶寬分配(Memory Bandwidth Allocation, MBA)。該技術(shù)旨在通過(guò)一系列的CPU指令從而允許用戶直接對(duì)每個(gè)CPU核心(附加了HT技術(shù)后為每個(gè)邏輯核心)的L2緩存、L3緩存(LLC--Last Level Cache )以及內(nèi)存帶寬進(jìn)行監(jiān)控和分配。
RDT一開(kāi)始是為解決云計(jì)算的問(wèn)題,在云計(jì)算領(lǐng)域虛擬化環(huán)境中,宿主機(jī)的資源(包括CPU cache和內(nèi)存帶寬)都是共享的。這帶來(lái)一個(gè)問(wèn)題就是:如果有一個(gè)過(guò)度消耗cache的應(yīng)用耗盡了L3緩存或者大量的內(nèi)存帶寬,將無(wú)法保障其他虛擬機(jī)應(yīng)用的性能。這種問(wèn)題稱為 noisy neighbor。
同樣對(duì)于我們的實(shí)時(shí)系統(tǒng)也是類似:由于L3 Cache多核共享,如果有一個(gè)過(guò)度消耗cache的非實(shí)時(shí)應(yīng)用耗盡了L3緩存或者大量的內(nèi)存帶寬,將無(wú)法保障x(chóng)enomai實(shí)時(shí)應(yīng)用的性能。
以往虛擬化環(huán)境中解決方法是通過(guò)控制虛擬機(jī)邏輯資源(cgroup)但是調(diào)整粒度太粗,并且無(wú)法控制處理器緩存這樣敏感而且稀缺的資源。為此Intel推出了RDT技術(shù)。在Intel中文網(wǎng)站的 通過(guò)英特爾 資源調(diào)配技術(shù)優(yōu)化資源利用視頻形象介紹了RDT的作用。
Intel的Fenghua Yu在Linux Foundation上的演講?Resource Allocation in Intel Resource Director Technology?可以幫助我們快速了解這項(xiàng)技術(shù)。
總的來(lái)說(shuō),RDT讓我們實(shí)現(xiàn)了控制處理器緩存這樣敏感而且稀缺的資源,對(duì)我們對(duì)實(shí)時(shí)性能提升有很大幫助(不僅限于xenomai,RTAI、PREEMPT-RT均適用)。
CAT(緩存分配技術(shù),Cache Alocation Technology),對(duì)最后一級(jí)緩存(L3 Cache)實(shí)現(xiàn)分區(qū),用戶可以通過(guò)限制每個(gè)核心能夠向其中分配緩存行的LLC數(shù)量,將LLC的部分分配給特定核心,使用該技術(shù)可以提升實(shí)時(shí)任務(wù)Cahe命中率,減少M(fèi)SI延遲和抖動(dòng),進(jìn)而提升實(shí)時(shí)性能。(不是所有intel處理器具有該功能,一開(kāi)始只有服務(wù)器CPU提供該支持,據(jù)筆者了解,6代以后的CPU基本支持CAT。關(guān)于CAT 見(jiàn)github),對(duì)于大多數(shù)Linux發(fā)行版,可直接安裝使用該工具,具體的cache分配策略可根據(jù)后面的資源隔離情況進(jìn)行。
?
?
sudo apt-get install intel-cmt-cat
?
?
TLB
與cache性質(zhì)一致。
分支預(yù)測(cè)
現(xiàn)代 CPU 的流水線級(jí)數(shù)非常長(zhǎng),一般都在10級(jí)以上,指令分支判斷錯(cuò)誤(Branch Mispredict)的時(shí)間代價(jià)昂貴。如果判斷預(yù)測(cè)正確,可能只需要一個(gè)時(shí)鐘周期;如果判斷錯(cuò)誤,就還是需要10-20 左右個(gè)時(shí)鐘周期來(lái)重新提取指令。
如下為對(duì)同一隨機(jī)組數(shù),排序與未排序情況下for循環(huán)測(cè)試:
數(shù)據(jù)有規(guī)律和無(wú)規(guī)律兩種情況下同一段代碼執(zhí)行時(shí)間相差巨大。
現(xiàn)代 CPU 的分支預(yù)測(cè)正確率已經(jīng)可以在一般情況下維持在 95% 以上,所以當(dāng)分支存在可預(yù)測(cè)的規(guī)律的時(shí)候,還是以性能測(cè)試的結(jié)果為最終的優(yōu)化依據(jù)。
Hyper-Threading
人們對(duì)CPU的性能的追求是無(wú)止境的,在CPU性能不斷優(yōu)化提高過(guò)程中,對(duì)于單一流水線,最佳情況下,IPC 也只能到 1。無(wú)論做了哪些流水線層面的優(yōu)化,即使做到了指令執(zhí)行層面的亂序執(zhí)行,CPU 仍然只能在一個(gè)時(shí)鐘周期里面取一條指令。
為使IPC>1,誕生了多發(fā)射(Mulitple Issue)和超標(biāo)量(Superscalar)技術(shù),伴隨的是每個(gè)CPU流水線上各種運(yùn)算單元的增加。但是當(dāng)處理器在運(yùn)行一個(gè)線程,執(zhí)行指令代碼時(shí),一方面很多時(shí)候處理器并不會(huì)使用到全部的計(jì)算能力,另一方面由于CPU在代碼層面運(yùn)行前后依賴關(guān)系的指令,會(huì)遇到各種冒險(xiǎn)問(wèn)題,這樣CPU部分計(jì)算能力就會(huì)處于空閑狀態(tài)。
為了進(jìn)一步“壓榨”處理器,那就找沒(méi)有依賴關(guān)系的指令來(lái)運(yùn)行好,即另一個(gè)程序。一個(gè)核可以分成幾個(gè)邏輯核,來(lái)執(zhí)行多個(gè)控制流程,這樣可以進(jìn)一步提高并行程度,這一技術(shù)就叫超線程,又稱同時(shí)多線程(Simultaneous Multi-Threading,簡(jiǎn)稱 SMT)。
由于超線程技術(shù)通過(guò)雙份的 PC 寄存器、指令寄存器、條件碼寄存器,在邏輯層面?zhèn)窝b為2個(gè)CPU,但指令譯碼器和ALU是公用的,這就造成實(shí)時(shí)任務(wù)運(yùn)行時(shí)在CPU執(zhí)行層面的不確定性,造成非實(shí)時(shí)線程與實(shí)時(shí)線程在同一物理核上對(duì)CPU執(zhí)行單元的競(jìng)爭(zhēng),影響實(shí)時(shí)任務(wù)實(shí)時(shí)性。
電源管理與調(diào)頻
我們知道CPU場(chǎng)效應(yīng)晶體管FET構(gòu)成,其簡(jiǎn)單示意圖如下。
當(dāng)輸入高低電平時(shí),CL被充放電,假設(shè)充放電a焦耳的能量。因?yàn)镃L很小,這個(gè)a也十分的小,幾乎可以忽略不計(jì)。為了提高CPU性能,不斷提高處理器的時(shí)鐘頻率,但如果我們以1GHz頻率翻轉(zhuǎn)這個(gè)FET,則能量消耗就是a × 10^9,這就不能忽略了,再加上CPU中有幾十億個(gè)FET,消耗的能量變得相當(dāng)可觀。
詳細(xì)的參考:https://zhuanlan.zhihu.com/p/56864499
為了省電,讓操作系統(tǒng)隨著工作量不同,動(dòng)態(tài)調(diào)節(jié)CPU頻率和電壓。但是調(diào)頻會(huì)導(dǎo)致CPU停頓(CPU停頓時(shí)間10us~500us不等),運(yùn)行速度降低導(dǎo)致延遲增加,嚴(yán)重影響實(shí)時(shí)性能。
除了調(diào)頻以外,另一個(gè)嚴(yán)重影響實(shí)時(shí)性的是,系統(tǒng)進(jìn)入更深層次的省電睡眠狀態(tài),這時(shí)的喚醒延遲長(zhǎng)達(dá)幾十毫秒。
Multi-Core
接收 IRQ 的 CPU 可能不是響應(yīng)者休眠的 CPU,在這種情況下,前者必須向后者發(fā)送重新調(diào)度請(qǐng)求,以便它恢復(fù)響應(yīng)者。這通常是通過(guò)處理器間中斷完成的,也就是IPI,IPI的發(fā)送和處理進(jìn)一步增加了延遲。
?
中斷周期及測(cè)試時(shí)長(zhǎng) | 最小 | 平均 | 最大 |
---|---|---|---|
100us 21h | 0.086us | 0.184us | 4.288us |
?
此外,多核LLC共享,NUMA架構(gòu)遠(yuǎn)端內(nèi)存訪問(wèn)等,均會(huì)導(dǎo)致訪問(wèn)延遲不確定。
DMA
DMA突發(fā)傳輸不確定占用總線帶寬,影響程序執(zhí)行;
總線動(dòng)態(tài)調(diào)頻省電等
other
其他影響因素有內(nèi)存、散熱。
提升內(nèi)存頻率可降低內(nèi)存訪問(wèn)延時(shí);使用雙通道內(nèi)存,這兩個(gè)內(nèi)存CPU可分別尋址、讀取數(shù)據(jù),從而使內(nèi)存的帶寬增加一倍,數(shù)據(jù)存取速度也相應(yīng)增加一倍(理論上),內(nèi)存訪問(wèn)延時(shí)得到縮短,進(jìn)而提升系統(tǒng)的實(shí)時(shí)性能;
處理器散熱設(shè)計(jì)不好,溫度過(guò)高時(shí)會(huì)引發(fā)CPU降頻保護(hù),系統(tǒng)運(yùn)行頻率降低影響實(shí)時(shí)性,熱設(shè)計(jì)應(yīng)確保在高工作量時(shí)的溫度不會(huì)引發(fā)降頻。
對(duì)于X86 CPU,雙通道內(nèi)存性能是單通道內(nèi)存的2. 5倍以上;正確的熱設(shè)計(jì)可使實(shí)時(shí)性提升1.4倍以上。
2.BISO(X86平臺(tái))
BISO需要針對(duì)實(shí)時(shí)系統(tǒng)進(jìn)行配置。優(yōu)化的BIOS設(shè)置與使用默認(rèn)BISO設(shè)置的實(shí)時(shí)性能差距高達(dá)9倍。
3.軟件
操作系統(tǒng):調(diào)度算法,同步機(jī)制,信號(hào)量類型,內(nèi)存管理策略,通信語(yǔ)義和中斷處理,是否使用mmu等,OS的類型與定位已經(jīng)決定了一些影響因素與實(shí)時(shí)之間的取舍。
資源的分配隔離:分配CPU專門對(duì)實(shí)時(shí)任務(wù)服務(wù)、將多余中斷隔離到非實(shí)時(shí)任務(wù)CPU上,分配CPU專門對(duì)實(shí)時(shí)任務(wù)服務(wù)可使L1 、L2 Cache只為實(shí)時(shí)任務(wù)服務(wù)。
動(dòng)態(tài)庫(kù)運(yùn)行時(shí)延遲綁定。
內(nèi)存分配算法時(shí)間不確定性。
實(shí)時(shí)任務(wù)的設(shè)計(jì),良好的軟件設(shè)計(jì)能更好的發(fā)揮實(shí)時(shí)性能。
其他,虛擬化、GUI等 。
4. GPU
硬件上GPU與CPU共享L3 Cache ,因此GUI會(huì)影響實(shí)時(shí)任務(wù)的實(shí)時(shí)性。intel建議根據(jù)GUI任務(wù)的工作負(fù)載來(lái)固定GPU的運(yùn)行頻率,且頻率盡可能低。減小GPU對(duì)實(shí)時(shí)任務(wù)實(shí)時(shí)性的影響。
三、優(yōu)化措施
原則:降低不確定性,提高可預(yù)期性,在此基礎(chǔ)上,再提高速度,降低延時(shí)。
比如,我們需要在確定的時(shí)間內(nèi)從廣州到深圳,如果駕車,途中會(huì)遇到多少個(gè)紅綠燈,有無(wú)堵車
等等,有很多不確定性。但是如果我們換坐動(dòng)車,就比駕車更具確定性,在此基礎(chǔ)上我們提高速度,換坐高鐵,廣州到深圳的延時(shí)將變得更小。
1. BIOS[x86]
?
? | ? |
---|---|
Disable Features | Intela Hyper-Threading Technology. |
Intel SpeedStep. | ? |
Intel Speed Shift Technology | ? |
C-States: Gfx RC6. | ? |
GT PM Support. | ? |
PCH Cross Throttling. | ? |
PCI Express_ Clock Gating. | ? |
Delay Enable DMI ASPM,DMI Link ASPM Control. | ? |
PCle _ASPM and SATA Aggressive LPM Support. | ? |
(For Skylake and Kaby Lake, also consider disabling Gfx Low Power Mode and USB Periodic SMl in BIOS.) | ? |
Enable Features | Legacy lO Low Latency |
Gfx Frequency | Set to fixed value as low as possible according to proper workload |
Memory Frequency | SA GV Fixed High |
?
2. 硬件
除處理器外,內(nèi)存方面,使用雙通道內(nèi)存,盡可能高的內(nèi)存頻率。
散熱當(dāng)面,針對(duì)處理器工作負(fù)載設(shè)計(jì)良好的散熱結(jié)構(gòu), 否則芯片保護(hù)會(huì)強(qiáng)制降頻,頻率調(diào)整CPU會(huì)停頓幾十上百us。
3. Linux
xenomai基于linux,xenomai作為一個(gè)小的實(shí)時(shí)核與linux共存,xenomai并未提供完整的硬件管理機(jī)制,許多硬件配置是linux 驅(qū)動(dòng)掌管的,必須讓linux配置好,給xenomai提供一個(gè)好的硬件環(huán)境,讓xenomai充分發(fā)揮其RTOS的優(yōu)勢(shì),主要宗旨:盡可能的不讓linux非實(shí)時(shí)部分影響xenomai,無(wú)論是軟件還是硬件。
3.1 Kernel CMDLINE
cpu隔離
多核情況下,設(shè)置內(nèi)核參數(shù)isolcpus=[cpu列表],將列表中的CPU從linux內(nèi)核SMP平衡和調(diào)度算法中剔除,將剔除的CPU用于RT應(yīng)用。如4核CPU平臺(tái)將第3、4核隔離來(lái)做RT應(yīng)用。
CPU編號(hào)從"0"開(kāi)始,列表的表示方法有三種:
numA,numB,...,numN
numA-numN
以及上述兩種表示方法的組合:
numA,...,numM-numN
例如:isolcpus=0,3,4-7表示隔離CPU0、3、4、5、6、7.
?
?
GRUB_CMDLINE_LINUX="isolcpus=2,3"
?
?
以上只是linux不會(huì)調(diào)度普通任務(wù)到CPU2和3上運(yùn)行,這是基礎(chǔ),此時(shí)還需要設(shè)置xenomai方面的CPU隔離,方法一,任務(wù)通過(guò)函數(shù)pthread_attr_setaffinity_np()設(shè)置xenomai任務(wù)只在CPU3和4上調(diào)度,隔離后的CPU的L1、L2緩存命中率相應(yīng)的也會(huì)得到提高。
?
?
cpu_set_t cpus; CPU_ZERO(&cpus); CPU_SET(2, &cpus);//將線程限制在指定的cpu2上運(yùn)行 CPU_SET(3, &cpus);//將線程限制在指定的cpu3上運(yùn)行 ret = pthread_attr_setaffinity_np(&tattr, sizeof(cpus), &cpus);
?
?
方法二,向xenomai設(shè)置內(nèi)核參數(shù)supported_cpus,指定xenomai支持的CPU,xenomai任務(wù)會(huì)自動(dòng)放到cpu2、cpu3上運(yùn)行,注意對(duì)于xenomai3.2以上版本,supported_cpus必須包含CPU0,否則xenomai內(nèi)核無(wú)法啟動(dòng)!!。
xenomai 內(nèi)核參數(shù)supported_cpus與linux不同,supported_cpus是一個(gè)16進(jìn)制數(shù),每bit置位表示支持該CPU,要支持CPU2、CPU3,需要置置位bit2、bit3,即supported_cpus=0x0c(00001100b)。
?
?
GRUB_CMDLINE_LINUX="isolcpus=2,3 xenomai.supported_cpus=0x0C"
?
?
注:linux內(nèi)核參數(shù)isolcpus=CPU編號(hào)列表是基礎(chǔ),否則若不隔離linux任務(wù),后面的xenomai設(shè)置將沒(méi)任何意義。
Full Dynamic Tick
將CPU2、CPU3作為xenomai使用后,由于xenomai調(diào)度是完全基于優(yōu)先級(jí)的調(diào)度器,并且我們已將linux任務(wù)從這兩個(gè)cpu上剔除,CPU上Tick也就沒(méi)啥用了,避免多余的Tick中斷影響實(shí)時(shí)任務(wù)的運(yùn)行,需要將這兩個(gè)cpu配置為Full Dynamic Tick模式,即關(guān)閉tick。通過(guò)添加linux內(nèi)核參數(shù)nohz_full=[cpu列表]配置。
nohz_full=[cpu列表]在使用CONFIG_NO_HZ_FULL = y構(gòu)建的內(nèi)核中才生效。
?
?
GRUB_CMDLINE_LINUX="isolcpus=2,3 xenomai.supported_cpus=0x0c nohz_full=2,3"
?
?
為什么是linux內(nèi)核參數(shù)呢?雙核下時(shí)間子系統(tǒng)中分析過(guò),每個(gè)CPU的時(shí)鐘工作方式是linux初始化并配置工作模式的,xenomai最后只是接管而已,所以這里是通過(guò)linux內(nèi)核參數(shù)配置。
注意:boot CPU(通常是0號(hào)CPU)會(huì)無(wú)條件的從列表中剔除。這是一個(gè)坑~
?
?
start_kerel() ->tick_init() ->tick_nohz_init() void __init tick_nohz_init(void) { ....... cpu = smp_processor_id(); if (cpumask_test_cpu(cpu, tick_nohz_full_mask)) { pr_warn("NO_HZ: Clearing %d from nohz_full range for timekeeping ", cpu); cpumask_clear_cpu(cpu, tick_nohz_full_mask); } ...... }
?
?
Offload RCU callback
從引導(dǎo)選擇的CPU上卸載RCU回調(diào)處理,使用內(nèi)核線程 “rcuox / N”代替,通過(guò)linux內(nèi)核參數(shù)rcu_nocbs=[cpu列表]指定的CPU列表設(shè)置。這對(duì)于HPC和實(shí)時(shí)工作負(fù)載很有用,這樣可以減少卸載RCU的CPU上操作系統(tǒng)抖動(dòng)。
"rcuox / N",N表示CPU編號(hào),‘x’:'b'是RCU-bh的b,'p'是RCU-preempt,‘s’是RCU-sched。
rcu_nocbs=[cpu列表]在使用CONFIG_RCU_NOCB_CPU=y構(gòu)建的內(nèi)核中才生效。除此之外需要設(shè)置RCU內(nèi)核線程rcuc/n和rcub/n線程的SCHED_FIFO優(yōu)先級(jí)值RCU_KTHREAD_PRIO,RCU_KTHREAD_PRIO設(shè)置為高于最低優(yōu)先級(jí)線程的優(yōu)先級(jí),也就是說(shuō)至少要使該優(yōu)先級(jí)低于xenomai實(shí)時(shí)應(yīng)用的優(yōu)先級(jí),避免xenomai實(shí)時(shí)應(yīng)用遷移到linux后,由于優(yōu)先級(jí)低于RCU_KTHREAD的優(yōu)先級(jí)而實(shí)時(shí)性受到影響,如下配置RCU_KTHREAD_PRIO=0。
?
?
General setup ---> RCU Subsystem ---> (0) Real-time priority to use for RCU worker threads [*] Offload RCU callback processing from boot-selected CPUs (X) No build_forced no-CBs CPUs ( ) CPU 0 is a build_forced no-CBs CPU ( ) All CPUs are build_forced no-CBs CPUs
GRUB_CMDLINE_LINUX="isolcpus=2,3 xenomai.supported_cpus=0x06 nohz_full=2,3 rcu_nocbs=2,3"
?
?
中斷
中斷隔離
xenomai用戶態(tài)實(shí)時(shí)應(yīng)用運(yùn)行時(shí),中斷優(yōu)先級(jí)最高,CPU必須響應(yīng)中斷,雖然有ipipe會(huì)簡(jiǎn)單將非實(shí)時(shí)設(shè)備中斷掛起,但是頻繁的非實(shí)時(shí)設(shè)備中斷產(chǎn)生可能引入無(wú)限延遲,也會(huì)影響實(shí)時(shí)任務(wù)的運(yùn)行。
因此多,核情況下,通過(guò)內(nèi)核參數(shù)irqaffinity==[cpu列表],設(shè)置linux設(shè)備中斷的親和性,設(shè)置后,默認(rèn)由這些cpu核來(lái)處理中斷。避免了非實(shí)時(shí)linux中斷影響cpu2、cpu3上的實(shí)時(shí)應(yīng)用,將linux中斷指定到cpu0、cpu1處理,添加參數(shù):
?
?
GRUB_CMDLINE_LINUX="isolcpus=2,3 xenomai.supported_cpus=0x0c nohz_full=2,3 rcu_nocbs=2,3 irqaffinity=0,1"
?
?
以上只是設(shè)置linux中斷的affinity,只能確保運(yùn)行實(shí)時(shí)任務(wù)的CPU2、cpu3不會(huì)收到linux非實(shí)時(shí)設(shè)備的中斷請(qǐng)求,保證實(shí)時(shí)性。
要指定cpu來(lái)處理xenomai實(shí)時(shí)設(shè)備中斷,需要在實(shí)時(shí)驅(qū)動(dòng)代碼中通過(guò)函數(shù)xnintr_affinity()設(shè)置,綁定實(shí)時(shí)驅(qū)動(dòng)中斷由CPU2、CPU3處理代碼如下。
?
?
cpumask_t irq_affinity; ... cpumask_clear(&irq_affinity); cpumask_set_cpu(2, &irq_affinity); cpumask_set_cpu(3, &irq_affinity); ... if (!cpumask_empty(&irq_affinity)){ xnintr_affinity(&pIp->irq_handle,irq_affinity);/*設(shè)置實(shí)時(shí)設(shè)備中斷的affinity*/ }
?
?
雖然ipipe會(huì)保證xenomai 實(shí)時(shí)中斷在任何CPU都會(huì)優(yōu)先處理,在實(shí)時(shí)設(shè)備中斷比較少的場(chǎng)合,我覺(jué)得把linux中斷與實(shí)時(shí)中斷分開(kāi)比較好;如果實(shí)時(shí)設(shè)備中斷數(shù)量較多,如果隔離就會(huì)造成實(shí)時(shí)中斷間相互影響中斷處理的實(shí)時(shí)性,這時(shí)候不指定實(shí)時(shí)中斷處理CPU比較好。
編寫xenomai實(shí)時(shí)設(shè)備驅(qū)動(dòng)程序時(shí),中斷處理程序需要盡可能的短。
禁用irqbanlance
linux irqbalance 用于優(yōu)化中斷分配,它會(huì)自動(dòng)收集系統(tǒng)數(shù)據(jù)以分析使用模式,并依據(jù)系統(tǒng)負(fù)載狀況將工作狀態(tài)置于 Performance mode 或 Power-save mode。簡(jiǎn)單來(lái)說(shuō)irqbalance 會(huì)將硬件中斷分配到各個(gè)CPU核心上處理。
處于 Performance mode 時(shí),irqbalance 會(huì)將中斷盡可能均勻地分發(fā)給各個(gè) CPU core,以充分利用 CPU 多核,提升性能。
處于 Power-save mode 時(shí),irqbalance 會(huì)將中斷集中分配給第一個(gè) CPU,以保證其它空閑 CPU 的睡眠時(shí)間,降低能耗。
禁用irqbanlance,避免不相干中斷發(fā)生在RT任務(wù)核。發(fā)行版不同,配置方式不同,以Ubuntu為例,停止/關(guān)閉開(kāi)機(jī)啟動(dòng)如下。
?
?
systemctl stop irqbalance.service systemctl disable irqbalance.service
?
?
必要的話直接卸載irqbalance。
?
?
apt-get remove irqbalance
?
?
x86平臺(tái)還可添加參數(shù)acpi_irq_nobalance禁用ACPI irqbalance.
?
?
GRUB_CMDLINE_LINUX="isolcpus=2,3 xenomai.supported_cpus=0x0c nohz_full=2,3 rcu_nocbs=2,3 irqaffinity=0,1 acpi_irq_nobalance noirqbalance"
?
?
intel 核顯配置[x86]
主要針對(duì)intel CPU的核顯,配置intel核顯驅(qū)動(dòng)模塊i915,內(nèi)核參數(shù)如下。
?
?
GRUB_CMDLINE_LINUX="i915.enable_rc6=0 i915.enable_dc=0 i915.disable_power_well=0 i915.enable_execlists=0 i915.powersave=0"
?
?
nmi_watchdog[x86]
NMI watchdog是Linux的開(kāi)發(fā)者為了debugging而添加的特性,但也能用來(lái)檢測(cè)和恢復(fù)Linux kernel?hang,現(xiàn)代多核x86體系都能支持NMI watchdog。
NMI(Non Maskable Interrupt)即不可屏蔽中斷,之所以要使用NMI,是因?yàn)镹MI watchdog的監(jiān)視目標(biāo)是整個(gè)內(nèi)核,而內(nèi)核可能發(fā)生在關(guān)中斷同時(shí)陷入死循環(huán)的錯(cuò)誤,此時(shí)只有NMI能拯救它。
Linux中有兩種NMI watchdog,分別是I/O APIC watchdog(nmi_watchdog=1)和Local APIC watchdog(nmi_watchdog=2)。它們的觸發(fā)機(jī)制不同,但觸發(fā)NMI之后的操作是幾乎一樣的。一旦開(kāi)啟了I/O APIC watchdog(nmi_watchdog=1),那么每個(gè)CPU對(duì)應(yīng)的Local APIC的LINT0線都關(guān)聯(lián)到NMI,這樣每個(gè)CPU將周期性地接到NMI,接到中斷的CPU立即處理NMI,用來(lái)悄悄監(jiān)視系統(tǒng)的運(yùn)行。如果系統(tǒng)正常,它啥事都不做,僅僅是更改 一些時(shí)間計(jì)數(shù);如果系統(tǒng)不正常(默認(rèn)5秒沒(méi)有任何普通外部中斷),那它就閑不住了,會(huì)立馬跳出來(lái),且中止之前程序的運(yùn)行。該出手時(shí)就出手。
避免周期中斷的NMI watchdog影響xenomai實(shí)時(shí)性需要關(guān)閉NMI watchdog,傳遞內(nèi)核參數(shù)nmi_watchdog=0.
?
?
GRUB_CMDLINE_LINUX="isolcpus=2,3 xenomai.supported_cpus=0x0c nohz_full=2,3 rcu_nocbs=2,3 irqaffinity=0,1 acpi_irq_nobalance noirqbalance i915.enable_rc6=0 i915.enable_dc=0 i915.disable_power_well=0 i915.enable_execlists=0 i915.powersave=0 nmi_watchdog=0"
?
?
nosoftlockup
linux內(nèi)核參數(shù),禁用 soft-lockup檢測(cè)器。
?
?
GRUB_CMDLINE_LINUX="isolcpus=2,3 xenomai.supported_cpus=0x0c nohz_full=2,3 rcu_nocbs=2,3 irqaffinity=0,1 acpi_irq_nobalance noirqbalance i915.enable_rc6=0 i915.enable_dc=0 i915.disable_power_well=0 i915.enable_execlists=0 i915.powersave=0 nmi_watchdog=0 nosoftlockup"
?
?
CPU特性[x86]
intel處理器相關(guān)內(nèi)核參數(shù):
nosmap
nohalt。告訴內(nèi)核在空閑時(shí),不要使用省電功能PAL_HALT_LIGHT。 這增加了功耗。但它減少了中斷喚醒延遲,這可以提高某些環(huán)境下的性能,例如聯(lián)網(wǎng)服務(wù)器或?qū)崟r(shí)系統(tǒng)。
mce=ignore_ce,忽略machine checkerrors (MCE).
idle=poll,不要使用HLT在空閑循環(huán)中進(jìn)行節(jié)電,而是輪詢以重新安排事件。 這將使CPU消耗更多的功率,但對(duì)于在多處理器基準(zhǔn)測(cè)試中獲得稍微更好的性能可能很有用。 它還使使用性能計(jì)數(shù)器的某些性能分析更加準(zhǔn)確。
clocksource=tsc tsc=reliable,指定tsc作為系統(tǒng)clocksource.
intel_idle.max_cstate=0?禁用intel_idle并回退到acpi_idle.
processor.max_cstate=0 intel.max_cstate=0 processor_idle.max_cstate=0?限制睡眠狀態(tài)c-state。
?
GRUB_CMDLINE_LINUX="isolcpus=2,3 xenomai.supported_cpus=0x0c nohz_full=2,3 rcu_nocbs=2,3 irqaffinity=0,1 acpi_irq_nobalance noirqbalance i915.enable_rc6=0 i915.enable_dc=0 i915.disable_power_well=0 i915.enable_execlists=0 nmi_watchdog=0 nosoftlockup processor.max_cstate=0 intel.max_cstate=0 processor_idle.max_cstate=0 intel_idle.max_cstate=0 clocksource=tsc tsc=reliable nmi_watchdog=0 nosoftlockup intel_pstate=disable idle=poll nohalt nosmap mce=ignore_ce"
?
?
3.2 內(nèi)核構(gòu)建配置
系統(tǒng)構(gòu)建時(shí),除以上提到的配置外(CONFIG_NO_HZ_FULL = y、CONFIG_RCU_NOCB_CPU=y、RCU_KTHREAD_PRIO=0),其他實(shí)時(shí)性相關(guān)配置如下:
CONFIG_MIGRATION=n、CONFIG_MCORE2=y[x86]、CONFIG_PREEMPT=y、ACPI_PROCESSOR =n[x86]、CONFIG_CPU_FREQ =n、CONFIG_CPU_IDLE =n;
經(jīng)過(guò)以上配置后可以使用latency測(cè)試,觀察配置前后的變化。關(guān)于latency,需要注意的是,測(cè)試timer-IRQ的latency時(shí),即用latency -t2命令來(lái)測(cè)試時(shí),xenomai默認(rèn)使用cpu0的timer,上面提到boot CPU(通常是0號(hào)CPU)會(huì)無(wú)條件的從nohz_full=[cpu列表]列表中剔除,所以latency -t2測(cè)試時(shí)你會(huì)發(fā)現(xiàn)沒(méi)什么變化,還可能會(huì)變差了(最壞情況差不多一致,平均值變大了),另外我們將linux中斷affinity全都設(shè)置為CPU0處理,這些中斷或多或少也會(huì)影響timer-IRQ的latency。
2021.5添加-- 最近發(fā)現(xiàn)xenomai內(nèi)核定時(shí)器affinity為cpu0的問(wèn)題已被社區(qū)修復(fù)。
三、軟件方面
使用靜態(tài)編譯語(yǔ)言
編寫高性能的代碼
盡量讓分支有規(guī)律性,使用likely()/unlikely()或編寫無(wú)分支代碼
利用cache局部性原理,防止偽共享
合理分配任務(wù)優(yōu)先級(jí)
盡量使用靜態(tài)庫(kù)
避免實(shí)時(shí)任務(wù)中進(jìn)行動(dòng)態(tài)內(nèi)存分配
驅(qū)動(dòng)程序中斷處理盡可能短等等
四、優(yōu)化結(jié)果對(duì)比
筆者對(duì)以上各個(gè)條件配置前后對(duì)比過(guò)實(shí)時(shí)性改善效果,均有不同程度的優(yōu)化效果,大家有興趣也可自行測(cè)試。
以下結(jié)果基于 i5-7200U 8GB單通道DDR4,64GB emmc5.0,未使用RDT技術(shù)。
1-3 在已裁剪桌面下,壓力加了內(nèi)存。
1. 原始性能測(cè)試。
只使用了xenomai,CONFIG_MIGRATION=n、CONFIG_MCORE2=y[x86]、CONFIG_PREEMPT=y、ACPI_PROCESSOR =n[x86]、CONFIG_CPU_FREQ =n、CONFIG_CPU_IDLE =n。
?
優(yōu)化項(xiàng) | 配置與否 |
---|---|
BISO | NO |
Linux | NO |
Full Dynamic Tick | NO |
Offload RCU callback | NO |
Full desktop | NO |
stress | -c 10 -m 4 |
?
2. 優(yōu)化BIOS設(shè)置。
?
優(yōu)化項(xiàng) | 配置與否 |
---|---|
BISO | YES |
Linux | NO |
Full Dynamic Tick | NO |
Offload RCU callback | NO |
Full desktop | NO |
stress | -c 10 -m 4 |
?
3. Linux配置優(yōu)化。
?
優(yōu)化項(xiàng) | 配置與否 |
---|---|
BISO | YES |
Linux | YES |
Full Dynamic Tick | YES |
Offload RCU callback | YES |
Full desktop | NO |
stress | -c 10 -m 4 |
?
4-6 未添加內(nèi)存壓力
4. 裁剪桌面。
保留完整Ubuntu桌面前,且經(jīng)所有配置:
?
優(yōu)化項(xiàng) | 配置與否 |
---|---|
BISO | YES |
Linux | YES |
Full Dynamic Tick | YES |
Offload RCU callback | YES |
Full desktop | NO—>YES |
stress | -c 10 |
?
裁剪桌面后:
裁剪前后對(duì)比:
5. Full Dynamic Tick啟用前后對(duì)比
裁剪桌面后,配置cpu0未啟用Full Dynamic Tick,cpu1啟用Full Dynamic Tick,加壓與未加壓對(duì)比。
?
優(yōu)化項(xiàng) | 配置與否 |
---|---|
BISO | YES |
Linux | YES |
Full Dynamic Tick | CPU0:NO |
;CPU1:YES | ? |
Offload RCU callback | CPU0==NO;CPU1: |
NO== | ? |
Full desktop | NO |
stress | -c 10 |
?
對(duì)比cpu0與cpu1,最壞情況沒(méi)有改善,但4us以上的latency改善明顯。
6.桌面、rcu、tick前后比對(duì)
帶桌面、未啟用rcu_nocb、未啟用Full Dynamic Tick-------->裁桌面、啟用rcu_nocb、啟用Full Dynamic Tick;
?
優(yōu)化項(xiàng) | 配置與否 |
---|---|
BISO | YES ? ? ? ? ? ?--> ? ? ? YES |
Linux | YES ? ? ? ? ? ?--> ? ? ? YES |
Full Dynamic Tick | NO --> YES |
Offload RCU callback | NO-->YES |
Full desktop | YES - >NO |
stress | -c 10 |
?
7.總對(duì)比
?
優(yōu)化項(xiàng) | 配置與否 |
---|---|
BISO | NO ? ? ? ? ? ?--> ? ? ??YES |
Linux | NO ? ? ? ? ? ?--> ? ? ??YES |
Full Dynamic Tick | NO ? ? ? ? ? ?--> ? ? ??YES |
Offload RCU callback | NO ? ? ? ? ? ? --> ? ? ??YES |
Full desktop | YES ? ? ? ? ? ? --> ? ? ??NO |
stress | -c 10?-m 4 |
?
四、實(shí)時(shí)性能測(cè)試
下面直接給出最終的應(yīng)用空間任務(wù)Jitter測(cè)試結(jié)果,使用的環(huán)境如下:
?
? | ? |
---|---|
CPU | intel 賽揚(yáng) 3865U@1.8GHZ |
Kernel | Linux 4.4.200 |
操作系統(tǒng) | Ubuntu 16.04 |
內(nèi)存 | 8GB DDR3-1600 雙通道 |
存儲(chǔ) | 64GB EMMC |
?
測(cè)試條件:在stress壓力下測(cè)試,同時(shí)一個(gè)QT應(yīng)用程序繪制2維曲線圖,QT CPU占用率99%。
?
?
stress -c 10 -m 4
?
?
測(cè)試時(shí)間:21155
測(cè)試命令:
?
?
latency -t0 -p 100 -P 99 -h -g result.txt
?
?
測(cè)試應(yīng)用空間程序,優(yōu)先級(jí)99,任務(wù)周期100us,測(cè)試結(jié)果輸出到文件result.txt。經(jīng)過(guò)接近10天的測(cè)試后,文件result.txt中l(wèi)atency分布結(jié)果如下:
?
?
# 21155 (periodic user-mode task, 100 us period, priority 99) # ----lat min|----lat avg|----lat max|-overrun|---msw| # 0.343| 1.078| 23.110| 0| 0| # Xenomai version: Xenomai/cobalt v3.1 # Linux 4.4.200-xeno ...... # I-pipe releagese #20 detected # Cobalt core 3.1 detected # Compiler: gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.12) # Build args: --enable-smp --enable-pshared --enable-tls PKG_CONFIG_PATH=:/usr/xenomai/lib/pkgconfig:/usr/xenomai/lib/pkgconfig0 1 0.5 1599357037 1.5 1621130106 2.5 56618753 3.5 4386985 4.5 3848531 5.5 3556704 6.5 3353649 7.5 3033218 8.5 2560133 9.5 2035075 10.5 1516866 11.5 1038989 12.5 680815 13.5 417124 14.5 224296 15.5 115165 16.5 58075 17.5 27669 18.5 11648 19.5 4648 20.5 1646 21.5 467 22.5 38 23.5 1
?
?
其中第一列數(shù)據(jù)表示latency的值,第二列表示該值與上一個(gè)值之間這個(gè)范圍的latency出現(xiàn)的次數(shù),最小0.343us,平均latency 1.078us,最大23.110us。可見(jiàn)xenomai的實(shí)時(shí)性還是挺不錯(cuò)的。
以上只是xenomai應(yīng)用空間任務(wù)的實(shí)時(shí)性表現(xiàn),如果使用內(nèi)核空間任務(wù)會(huì)更好。當(dāng)然這只能說(shuō)明操作系統(tǒng)能提供的實(shí)時(shí)性能,具體的還要看應(yīng)用程序的設(shè)計(jì)等。
此外,該測(cè)試基于X86平臺(tái),X86處理器的實(shí)時(shí)性與BIOS有很大關(guān)系,通常BIOS配置CPU具有更高的吞吐量,例如超線程、電源管理、CPU頻率等,畢竟BIOS不是普通開(kāi)發(fā)者能接觸到的,如果能讓BIOS對(duì)CPU針對(duì)實(shí)時(shí)系統(tǒng)配置的話,實(shí)時(shí)性會(huì)更好。如下圖所示,平均抖動(dòng)幾乎在100納秒以內(nèi)。
編輯:黃飛
?
評(píng)論
查看更多