有效利用RTOS編程概念支持先進的多線程架構
像MIPS技術公司最新的MIPS32 34K內核這樣的多線程架構正吸引著越來越多的關注,這是因為這種架構無需增加太多的芯片資源或功耗即可獲得可觀的性能增益。這種硬件多線程的關鍵優勢是,它能使用處理器在等待緩沖回填的空閑周期處理其它線程的指令。
使消費類設備應用程序適應多線程環境的代價一般很小,因為大多數程序已經設計為成組的半獨立線程。應用程序線程可以分配給處理器中用于處理單線程的專用硬件資源。多個線程可以被同時分配給這樣的硬件,并通過共享CPU周期獲得最大的效率。
嵌入式運算面臨性能障礙
消費類設備和其它嵌入式計算產品的制造商正在增加Wi-Fi、VoIP、藍牙、視頻等各種新的功能,以往功能的增加都要靠大幅提升處理器的時鐘速度來實現。臺式機的時鐘速度目前已經增加到3GHz以上,即使嵌入式設備也接近GHz級。
但在嵌入式應用領域,這種方法很快就失去了可行性,因為大多數設備的運行收到功耗和資源的約束,這些都限制了處理器速度的進一步提高。時鐘周期速度的提高將顯著地增大功耗,因此對越來越多的嵌入式設備來說高周期速度將不大可行。另外,處理器速度的進一步提高并不能帶來相應的性能改善,因為存儲器性能的提高跟不上處理器速度提高的步伐,如上圖1所示。
處理器速度已經比存儲器快很多,在許多應用場合處理器有一半以上的時間在等待緩存行(cache line)回填數據。每當緩存丟失(cache miss)或需要片外存儲器訪問時,處理器就需要從存儲器加載緩存行,將這些字寫進緩存,再將舊的緩存行寫進存儲器,最后恢復線程。
MIPS公司指出,每千條指令接受25次緩存丟失(對多媒體代碼來說是一個合理的值)的高端可綜合內核如果必須等待50個緩存填充周期,那么將有50%以上的時間處于停止狀態。由于處理器速度仍在不斷提高,而且比存儲器速度的提高幅度大得多,這類問題將變得越來越突出。
圖1:處理器速度超過存儲器。
多線程技術
多線程技術解決了這一難題,它可以利用處理器原本用于等待存儲器訪問的空閑時間處理多個并行程序執行線程。當一個線程停下來等待存儲器響應時,另外一個線程會馬上提交給處理器,從而保持運算資源的充分利用。
值得注意的是,傳統處理器不能采用這種方法,因為它需要大量指令周期才能完成線程之間的切換。要想使這種方法順利工作,多個應用程序線程必須立即有效,并能逐周期運行。
34K處理器是來自面向消費類設備市場的嵌入式處理器主要提供商的首個多線程產品。每個軟件線程在線程環境(Thread Context, TC)上執行,一個TC包括一整套通用寄存器和一個程序計數器(program counter)。
每個TC都有自己的指令預取隊列,所有隊列都完全獨立。這意味著內核能在線程間逐周期地進行切換,因此可以避免軟件中產生開銷。增加更多的TC只需增加很少的額外硅片。TC共享大部分CPU硬件,包括執行單元、ALU和緩存。而且,增加一個TC并不要求CPU擁有另外一個OS軟件運行CPU所需的CP0寄存器拷貝。
一組共享CP0寄存器以及與之相關的TC即組成一個虛擬處理單元(VPE)。一個TC運行一個線程,一個VPE管理一個操作系統:如果有兩個VPE,那么就可以有兩個獨立的操作系統,或一個SMP風格的操作系統。帶一個TC的VPE看起來就像是傳統的MIPS32架構CPU,并且完全兼容MIPS架構規范-其實就是一個完整的虛擬處理器。
34K內核最多可以有9個TC和2個VPE。TC到VPE的聯系取決于運行時間。默認情況下所有準備執行的TC都平等分享處理時間,但34K內核也能在某個特殊要求線程可能會“挨餓”的情況下讓某個程序影響線程調度,也就是說軟件可以控制每個線程的服務質量(QoS)。應用軟件與硬件策略管理器(Policy Manager)互動,策略管理器向各個TC分配動態改變的優先級。然后由硬件分發調度器將線程逐個周期地分配給執行單元,從而滿足QoS要求。
在像34K這樣的多線程環境中,性能可以大大地提高,因為只要一個線程處于等待存儲器訪問狀態,另外一個線程就會占用空閑下來的處理器周期。上圖2表明了多線程是如何加快程序執行速度的。當只有線程0運行時,13個處理器周期中只有5個用于指令執行,剩下7個全部在等待緩存行的回填。在這種使用傳統處理方式的情況下效率只有38%。
圖2:多線程提高了管線效率。
增加線程1就可能使用上述5個用于等待的處理器周期。現在13個處理器周期中用到了10個,效率提高到77%,與最基本情況相比速度加快了一倍。增加線程2后可以完全加載處理器資源,13個執行指令周期可以全部用上,效率達到100%。相比基本情況速度提高263%。
采用EEMBC性能基準的測試表明,34K內核與24KE系列產品相比,只用兩個線程就可以提速60%,而硅片尺寸只增加14%,如圖3所示。
圖3:EEMBC基準性能例子表明只用兩個線程性能就有60%的提高。
使軟件適應多線程
多線程方法的關鍵優勢是在大多數情況下現有軟件只需做極少量的修改就能順利運行。大多數消費類設備程序已經寫成一系列的半獨立線程。每個線程可以被自動或人工地分配給專門的硬件TC。
如果當前正在執行的線程由于緩存丟失或其它原因引起的時延而無法繼續運行,CPU執行機制就會從那個TC切換到另外一個TC,該TC的線程可以在不浪費CPU周期的情況下運行。程序中線程越多,利用等待存儲器訪問周期的可能性就越高。
多線程處理對使用或考慮使用RTOS的任何人來說都是非常理想的,因為RTOS程序本身就具有多線程特性。無需為多線程重新編寫RTOS程序,因為RTOS可以在程序控制下自動將程序線程映射為TC,其映射方式與將線程映射為傳統處理器的方式相同。
如果線程數比TC多,通常需要用到傳統的環境切換(context switch)。這些環境切換與傳統處理器中的是一樣的。RTOS保存當前任務的狀態,加載另外一個任務的環境并開始執行。多線程環境顯然要比傳統處理器更適合更多環境的切換,所實現的環境切換速度也更快。
Linux/Windows與RTOS的多線程比較
本節重點介紹相對Linux和嵌入式Windows版本等操作系統而言快速RTOS的優勢。Linux的典型實時性能在數百微秒到數毫秒。但在最壞情況下Linux實時性能并不理想。而快速RTOS可以提供確定的實時性能,在單線程處理器上可以達1到2毫秒,在多線程處理器上還會更快。
圖4:將線程映射為TC
RTOS將唯一資源分配給唯一的TC。傳統的做法是將單浮點單元(FPU)分配給TC0。任何執行硬件級浮點運算的線程都需要被映射為TC0,因此所有這類線程必須共享TC0。這就形成了多種有趣的編程選擇,特別是用硬件還是軟件實現浮點運算的選擇。
用硬件實現浮點運算顯然速度會更快,但另一方面需要共享FPU。如果線程只做少量的浮點運算,那么用軟件實現將更有意義,而需要密集浮點運算的線程通常要用硬件實現,并被映射到TC0。值得注意的是,這個修改不需要記錄,因為是否用硬件或軟件浮點實現的決定可以由編譯器切換實現。
給線程分配權重
如果程序沒有給各個線程定義權重,那么程序調度器就會給所有線程分配相同的權重,另外也可以使用時間分段技術使線程依據用戶指定的權重共享CPU周期。分配權重相當于將適當比例的CPU周期分配給各個具體線程。線程權重由RTOS透明地映射為硬件TC。
一些現有程序是針對傳統處理器設計的,其前提條件是假設在有高優先級的線程準備好時低優先級線程將被禁止運行。在嵌入式編程環境中,準備好的意思是線程運行所必需的全部條件都得到了滿足,阻止它運行的唯一因素是它的優先級。
多線程可破壞這種條件,因為無論高優先級線程是否停止,低優先級線程都能運行。編寫取消這種狀態的代碼可優化性能。
另外一方面,根據這種條件編寫的現有代碼無需修改就能運行在多線程處理器上,只需簡單地設置操作系統開關,使其只允許相同優先級的線程同時被加載到TC。在設置這個開關時,需要確保給那些能夠并行運行的線程盡量分配相同的優先級。
可中斷的重要性
在傳統的嵌入式應用中中斷是非常重要的,因為它們提供了主要的、在許多情況下也是唯一的線程間切換方式。中斷在多線程應用中也起著相同的作用,但有一個重要的區別,即在多線程應用中,線程間的切換不僅要通過中斷,還要使用空閑CPU周期。
需要盡量避免在修改關鍵數據結構時中斷某個線程,同時起用另外一個線程對同一結構作其它修改。這將導致數據結構處于不一致的狀態,極易引起災難性后果。
大多數傳統應用解決這個問題的方法是,當ISR或系統服務正在修改RTOS中關鍵的數據結構時暫時鎖住中斷。這種方法可靠地阻止了任何其它程序跳進來對執行代碼正在使用的關鍵區域做出不恰當的修改。
然而在多線程環境中這種方法是不夠的,因為有可能被切換到不受中斷鎖定控制的不同TC,從而可能對關鍵區域做出修改。該問題可以利用34K架構中的DMT指令解決,當數據結構在修改狀態時可禁止多線程功能。
除了這些相對簡單的例外情況外,設備代碼在從傳統設備移植到多線程設備時無需修改就能直接運行。因此,我們能夠利用以往被傳統RISC處理器浪費的CPU周期,充分發揮多線程性能優勢。多線程可以滿足當前和未來需要高性能的消費類、網絡、存儲和工業設備應用要求,而成本和功耗只有少許的增加。
與主要的競爭技術--多內核技術相比,多線程有更小的硅片面積和更低功耗的優勢,而且編程簡單,現有程序只需做少量修改甚至不用修改就能運行。多內核方法也有它自己的優勢和強項,因此沒有理由證明這兩種方法不能融合出一種最佳方法。在要求高性能、低成本和最小功耗的應用場合,多線程是一種極具競爭力的方案。
作者:
John A. Carbone
產品行銷副總裁
Express Logic公司
評論