周耀陽 韓博陽 藺嘉煒 王凱帆 張林雋 余子濠 唐 丹,3 王 卅,2 孫凝暉包云崗,2
1 (處理器芯片全國重點實驗室(中國科學院計算技術研究所)北京 100190)
2 (中國科學院大學計算機科學與技術學院 北京 100049)
3 (北京開源芯片研究院 北京 100080)
4 (香港大學電機電子工程系 香港 999077)
在近幾年的芯片敏捷開發浪潮中,得益于Chisel,BlueSpec,PyMtl 等新興的硬件描述語言和Rocketchip等SoC 平臺,直接基于寄存器傳輸級(register-transfer level,RTL)描述進行CPU 架構的設計變得越來越常見[1-6].隨著社區的不斷發展,基于這些語言的開源設計架構越來越先進,其設計也越來越復雜,例如加州大學伯克利分校開源的Boom 和中國科學院計算技術研究所開源的香山處理器[4,6-8].復雜的設計對現有的性能評估設施提出了更高的要求,例如AWS 的云化FPGA 已經難以容納目前最復雜的開源處理器核[4].
為了使設計規模不受限制,部分工作[4]采用了基于RTL 軟件仿真器的技術路線.但是對于復雜設計而言,常用的RTL 軟件仿真器(例如Verilator[9]和VCS)仿真復雜設計的速度僅有500~3 000 cycle/s[4].為了加速仿真流程,利用采樣和功能預熱來減少仿真指令數是最常見的方法[10-12].雖然這些方法起初是在GEM5等CPU 架構模擬器上誕生,但在RTL 軟件仿真器上,有越來越多的工作通過采樣和檢查點等方法來減少仿真指令數、縮短仿真時間[4,13].
采樣方法基于機器學習或者統計學方法從冗長的程序中選擇很少一部分片段作為代表來進行性能測量,獲得程序性能計數器,用于估算整個程序的性能(如圖1 所示).這些采樣方法的典型代表是SimPoint[10]和SMARTS[11].對于SPECCPU?這樣的大型程序而言,這些采樣方法[10-11]可以將總測量指令數縮減到千分之一以下.

Fig.1 Existing sampling-based simulation methods圖1 現有的基于采樣的仿真方法
采樣方法會引入冷啟動問題,即程序在特定采樣點(region of interest, ROI)開始執行時,處理器的微架構狀態與從頭開始運行時是不同的.為此,引入了預熱機制,即在采樣點開始之前增加一段不參與數據統計的預熱執行階段(如圖1(b)所示),使微結構狀態更貼近從頭開始執行[10-11,14].在提高其準確度的同時,預熱也造成了額外的仿真指令數.為此,通過功能預熱、虛擬化預熱等方法來降低預熱帶來的額外開銷[11,15-17].
如圖2 所示,即使應用了現有的檢查點技術[4]和Verilator 的多線程加速[9],仍然存在需要仿真超30 h的檢查點(每個檢查點均采用Verilator 開啟16 線程仿真,運行40M 指令).研究表明,為了降低單檢查點的指令數,可以縮短單個檢查點的采樣長度[10-11],但不能縮短預熱長度,否則會損失性能[14,18](詳見1.3節).因此預熱時間占比會從現在的約50%進一步上升,可見,加速RTL 預熱非常重要.

Fig.2 Emulation time distribution of 492 checkpoints from SPECCPU? 2006圖2 來自SPECCPU? 2006 的492 個檢查點的仿真時間分布
為了加速RTL 仿真預熱,本文通過profiling(嘗試不同的預熱長度)根據程序預熱需求將預熱過程分為3 段,如圖3 所示.對這3 段分而治之:1)完全跳過非必要預熱;2)對可功能預熱段采用功能預熱加速;3)對必須采用RTL 仿真的部分使用并行加速和調度優化.為了達成修改方案,需要回答3 個問題:1)在RTL 仿真極其緩慢的背景下,面對快速迭代的設計,如何高效地profiling;2)在快速迭代的設計上,如何實現可復用的功能預熱;3)在任務時長分布不均、多任務間存在性能干擾的情況下,如何調度計算資源盡快完成全細節仿真.

Fig.3 Optimization overview of HyWarm: Existing fixed warm up duration is divided into three segments圖3 HyWarm 的優化概覽:將現存固定預熱長度分為3 段
問題1:在RTL 仿真極其緩慢的背景下,面對快速迭代的設計,如何高效地profiling.現有工作通過profiling 來獲取應用的實際預熱需求(指令數),這可以縮短不必要的預熱長度[14,17,19-20].但每當面對新設計(比如緩存容量增加)時,重新profiling 反而增加了全細節仿真指令數[20].面對該挑戰,我們發現架構模擬器不僅運行速度比RTL 快,而且可以得到近似的程序預熱需求(實驗數據見2.1 節和4.2 節).因此,用模擬器替代RTL 仿真進行profiling可以兼顧速度和準確度.
問題2:在快速迭代的設計上,如何實現可復用的功能預熱.盡管模擬器上的功能預熱已經得到了充分研究,但是沒有現存的在RTL 上實現功能預熱的方法.其中,最大的難題是我們很難錨定RTL 生成的C++數據結構進行功能預熱.因為從RTL 生成的C++數據結構可讀性非常差,且變量名和存儲結構會隨著設計的變化而變化.面對該挑戰,我們發現雖然生成的C++數據結構會改變,但是總線協議是相對固定的,例如AMBA[21],TileLink[22].如果錨定通用的緩存協議實現緩存功能預熱,那么只要總線協議不改變就可以復用功能預熱模塊.
問題3:在任務時長分布不均,多任務間存在性能干擾的情況下,如何調度計算資源盡快完成全細節仿真.圖2 表明一部分負載的仿真時間較長,成為了影響仿真時間的最重要因素,因此任務調度需要避免負載不均衡.此外,在應用滿載運行多個多線程任務時觀察到了相較于單任務運行時的45%的性能損失,如表1 所示,其中IPS 是每秒仿真的指令數量,仿真對象為香山處理器運行dhrystone.這促使我們重新思考多線程和多任務對全系統吞吐的影響,并得出了CPU 核分簇方案(見2.2 節).在此基礎上,以CPU 簇為調度粒度,對任務采用長作業優先(long job first, LJF)調度算法,該算法被證明最大完成時間在最差情況下只有最優調度的4/3[23-24].

Table 1 Emulation Speed of Verilator with Different Parallelism on AMD EPYC 7H12 Server with 64 Cores表1 在AMD EPYC 7H12 64 核服務器上運行不同并行任務數的Verilator 的仿真速度
綜上,本文提出了HyWarm 框架,它包括:1)基于架構模擬器進行預熱需求分析,可以快速獲得負載的預熱需求的工具WarmProfiler;2)通過錨定總線協議實現可復用的RTL 功能預熱的工具TLWarmer;3)最大化系統吞吐、縮短最大完成時間的分簇LJF調度算法.
我們在香山處理器[4]上實現了HyWarm 框架.其中,TLWarmer 將8 MB 緩存預熱時間從10~100 h 縮短到少于0.5 h.相對于MINJIE[4]平臺的檢查點采樣方案,HyWarm 能達到接近25M 指令全細節預熱的準確度(HyWarm 的 L1 缺失懲罰準確率為95.1%,分支的每千條指令分支預測錯誤數(MPKI)準確率為 91.6%;25M 全細節預熱的L1 缺失懲罰準確率為91.3%,分支MPKI 準確率為94.1%).在準確率與基線配置(25M)接近的情況下,相比于25M 預熱+隨機調度的基線,HyWarm 將仿真完成時間縮短了53%.
本文的貢獻包括3 個部分:
1)提出了 HyWarm 預熱框架,通過架構模擬器識別應用的預熱需求,預測應用仿真時長;然后利用功能預熱和調度優化來縮短仿真時長.
2)提出了一種利用總線協議來進行緩存功能預熱的思路,并在TileLink 協議上實現,大幅縮短了功能預熱的時間.
3)分析了多核擴展和任務間性能干擾對Verilator仿真的性能影響,得出了效率最優的CPU 簇劃分策略,并在此基礎上應用LJF 調度算法來減少最大完成時間.
在芯片設計中,硅前性能測算對設計決策至關重要.現存的硅前性能測算手段主要包括3 類:RTL軟件仿真器、基于FPGA 的硬件加速仿真和基于仿真加速器的硬件加速仿真.表2 列出了芯片設計過程中進行仿真的4 種常用方法.

Table 2 Comparison of Commonly Used RTL Performance Evaluation Methods表2 常用的RTL 性能評估方法對比
此前,基于FPGA 的硬件加速仿真被充分研究,有的工作[25]優化了從CPU 模塊到FPGA 資源的映射,使得基于FPGA 的硬件加速仿真達到更高的運行頻率.有的工作[26]利用AWS 的云FPGA 來提高FPGA硬件加速的易用性.還有工作[27]利用FPGA 進行電路的功耗預測和建模.然而文獻[25-27]的工作都未能解決FPGA 的資源容量限制CPU 設計規模的問題[28-29],例如AWS F1 提供的vu9p FPGA 芯片就因為BRAM 和LUT 的開銷無法容納雙核標配的香山處理器[4].
在工業界,商業公司設計復雜SoC 時往往會使用仿真加速器,例如Cadence Palladium[30],Mentor Veloce[31]和Synopsys Zebu[32].仿真加速器擁有比FPGA 更高的擴展性,但是一臺仿真加速器的價格往往超過一千萬人民幣,這導致一個商業公司內部往往只有少量的仿真加速器.而且仿真加速器的仿真頻率一般在幾個MHz[4],比FPGA 慢1%~10%,用一臺仿真加速器來進行SPECCPU?2006 的測評至少需要幾個月的時間,在實際的場景中也是不可接受的.
相比于FPGA 和仿真加速器,RTL 軟件仿真擁有最好的可擴展性、易調試性,它可以同時支持波形和文字打印,并且電路的規模只受限于服務器的內存容量.但RTL 軟件仿真器速度非常慢,根據仿真性能估算,如果用最快的開源RTL 仿真平臺Verilator 來仿真香山處理器并評估SPECCPU?2006/2017 的性能,預估需要超過7 年的時間[4,9].
開源RTL 仿真器Verilator 和商業仿真器VCS 是被開源處理器社區廣泛采用的兩大仿真平臺.Verilator 通過塊重排序、網表級優化獲得了比商業仿真器更快的仿真速度.Verilator 還能將仿真任務劃分到多個CPU 核上并行執行來提升仿真速度.ESSENT使用了重用不變信號等技術,獲得了相較于Verilator 1.5~11.5 倍的性能提升[33].然而即使獲得了近1 個數量級的提升仍然無法讓RTL 仿真速度勝任香山處理器的性能評估(預計耗時數月到1 年).
針對RTL 軟件仿真速度慢的問題,可以采用體系結構研究中常用的采樣方法來減少仿真指令數.SimPoint[10]和SMARTS[11]是最廣泛使用的2 種采樣方法.SimPoint 通過功能模擬器獲得基本塊向量,然后對基本塊向量進行聚類,得到具有代表性的程序片段和相應的權重,并通過運行這些片段來估算整體性能,如 圖4(a)所示.SMARTS 則在程序中選取大量且均勻的采樣點來估算整體性能,如 圖4(b)所示.二者都可以大幅減少仿真的指令數(減少到0.1%以下).此外,在SimPoint 和SMARTS 的基礎上,后續的工作改進了預熱方法[11,14,16-17,34-36],支持多線程應用[37-39], 捕捉微結構相關特征[40].雖然文獻[10-11]的采樣算法可以減少總仿真指令數并加速RTL 軟件仿真,但是這些算法無法直接應用于RTL 軟件仿真.GEM5 模擬器與RTL 仿真器最大的不同在于GEM5 為從功能模型中串行化得到體系結構狀態、從串行化的體系結構狀態中恢復狀態到微架構模型做了很多支持,但是RTL 仿真器缺乏類似的串行化和去串行化支持.

Fig.4 Mainstream sampling-based simulation methods圖4 主流的基于采樣的仿真方法
為了解決在RTL 上對體系結構狀態去串行化的問題,現有研究采用通過軟件自動去串行化的方法來實現跨硬件平臺的體系結構狀態檢查點[4,13].這些方法的共同點在于,它們都選擇了一個在指令集定義中較穩定的接口,并通過軟件的方式來恢復.Dromajo 使用了RISC-V 調試模塊來恢復體系結構狀態[13,41];而香山處理器采用了RISC-V 特權指令來恢復體系結構狀態[4].這2 種體系結構檢查點的實現方法都可以支持SimPoint 等采樣方法,從而讓RTL 軟件仿真的時間大幅度縮短.例如MinJie 平臺所使用的檢查點技術[4]讓香山處理器在理論上需要數年才能完成,而SPECCPU?2006[42]的仿真在2~14 天就可以完成.
圖2 展示了采用體系結構檢查點和SimPoint 采樣算法后,香山處理器仿真檢查點的時間(40M 指令).這些負載的仿真時間分布非常不均勻,假設計算資源充足,那么多數負載可以在10 h 內完成,而剩下的負載需要超過30 h 才能完成,少數檢查點由于運行時間過長已經成為整個流程的關鍵路徑.
為了進一步加速性能測算,可以降低單個檢查點的采樣長度.研究表明,在總采樣指令數一定的前提下,減少每個采樣片段執行的指令并相應地增加采樣片段個數,不會損失準確度[10-11].例如,將N個20M 指令的采樣片段變為4N個5M 指令的片段.雖然這種方法能保證準確度,但會增加仿真的總指令數.例如從(20M+20M)×N變為(20M+5M)×4N,總仿真指令數增加了150%,預熱指令數占比上升到80%.因此,為了縮短仿真時間,需要縮短預熱時間.
已有研究表明部分應用的預熱需求超過200M[14,18],因此200M 指令的預熱長度不能進一步縮短.雖然預熱長度無法縮短,但是研究者發明了“功能預熱”來減少全細節預熱的長度.具體而言,功能預熱通過功能模擬以更快的速度預熱一部分微結構模塊,然后再用全細節仿真來預熱整個CPU.
功能預熱是最常用的預熱加速技術,它與全細節預熱的最大區別是用功能CPU 來驅動緩存,以提高預熱速度.例如,在GEM5 模擬器中,可以用一個運行速度較快的順序CPU 驅動多級緩存,待緩存充分填充緩存塊之后,再將CPU 換為亂序執行架構.得益于良好的軟件接口,在GEM5 模擬器切換CPU 時只需要將SoC 的CPU 指針指向亂序CPU 即可.
但在RTL 中,我們難以實現一個針對RTL 生成的C++數據結構的功能預熱模塊.因為處理器設計迭代會帶來新的RTL,導致RTL 生成的C++代碼的數據結構也會隨之變化,舊的功能預熱模塊難以復用到新的設計上.此外,功能預熱模塊還需要精確地復刻RTL 中的微結構狀態.即使業界頂尖的公司進行該工作也是非常困難的,因為對齊模擬器的工作量巨大[43-44].因此,為了實現RTL 功能預熱需要新的解決方案.
雖然某些應用的預熱需求很長,但是文獻[14,18]的結果表明部分應用的預熱需求很短.因此,可以通過縮短這部分應用的預熱長度來節省預熱時間.為了獲得這部分應用的預熱需求,需要對多種不同的預熱長度進行嘗試,并找到性能準確度損失較小的最短預熱長度.在后續的重復運行中,可以采用較短的預熱長度.但是這種profiling 方法并不適用于快速迭代的架構,也不適合架構參數搜索,因為隨著緩存架構和規格的變化,舊的profiling 結果會失效,導致profiling 的開銷無法均攤到多次的運行中[20].
1.2 節和1.3 節總結了RTL 軟件仿真中現存的采樣技術尚未解決的3 個挑戰:1)RTL 仿真缺乏功能預熱的基礎設施,且難以實現針對RTL 生成的C++數據結構的功能預熱模塊;2)面對架構和參數的變化,難以通過多次運行來均攤profiling 預熱需求的開銷;3)少數的檢查點由于運行時間過長已經成為整個流程的關鍵路徑.
關于RTL 預熱,我們有3 個觀察:
1)CPU 的部分模塊使用穩定的總線協議,例如緩存模塊通常基于TileLink 協議[3,22]或者AMBA 總線協議[21].雖然緩存內部的微結構設計會不斷迭代,但這些總線協議是穩定的.因此,只要設計一套基于總線協議而非針對微架構的功能預熱方法,就可以在多個版本的RTL 中重復使用功能預熱模塊.
2)同一應用對不同模塊的預熱需求不同,特別是分支預測模塊與緩存模塊的預熱需求通常存在較大差異.如圖5 所示,sjeng 的分支MPKI 在預熱長度為25M 時飽和,而L2 MPKI 在預熱長度為4M 時飽和.因此,如果實現了功能預熱,并提前了解某個應用對各個微結構模塊的預熱需求,可以針對性地調節功能預熱和全細節預熱的長度,以盡可能縮短完整預熱所需時間.而為了“預知”負載的“可功能預熱段”,需要提前測試多種可能的預熱長度,從中選取既高效又精確的預熱長度.

Fig.5 Warm up demand curve of sjeng圖5 sjeng 的預熱需求曲線
3)不同應用的預熱需求不同.4.2 節的預熱需求分析實驗表明,約38%檢查點的預熱需求大于20M;約62%檢查點的預熱需求小于20M,其中約57%需求小于5M.如果我們能預知負載的預熱需求,就可以在預熱需求較小的應用上節約大量時間,同時為預熱需求大的應用提供更長的預熱以獲得更高的準確性.
為了通過profiling 獲得負載的預熱需求,需要搜索多種不同的預熱長度,這可能導致較大的時間開銷.在搜索過程中,需要測量不同預熱長度下的緩存MPKI 或者分支MPKI,從而構建如圖6 所示的曲線;然后找到讓MPKI 滿足誤差閾值的最小預熱長度.在該過程中,必須測試多個預熱長度:如果對9 個可選的預熱長度進行二分查找(假設曲線單調),那么至少需要仿真4 個點,而仿真指令數量會增加約4 倍.增加的仿真工作量如果無法通過多次運行均攤,那么profiling 后縮短預熱長度的收益無法填補profiling的代價[20].

Fig.6 Warm up length search process圖6 預熱長度搜索過程
面對預熱需求搜索的挑戰,我們有2 個觀察:1)架構模擬器的仿真速度是RTL 仿真器的100 倍左右(Verilator 仿真香山約1KCPS (cycle per second);GEM5約100KIPS(kilo instruction per second)),如果可以用架構模擬器進行profiling,那么整體的仿真時間就不會被profiling 拖累.2)相同的微結構算法的不同實現經過相同長度的預熱之后留存的狀態往往是相似的.這是因為受到了文獻[45]的啟發,文獻[45]設計了簡化的LRU 緩存用來恢復完整實現的LRU 緩存的狀態,并取得了不錯的準確率,并在預熱需求上也觀察到了類似的現象,如圖7 所示,同為 32KB 的TAGE預測器,雖然由于循環預測器[46]和Statistical Corrector[47]的區別導致香山處理器與GEM5 的MPKI 存在差異,但是二者的預熱需求都在50M 條指令附近飽和(更多數據見4.2 節和4.3 節).綜合這2 個觀察,為了高效地搜索預熱需求,可以用微結構算法、規格相似的架構模擬器來近似估計RTL 的預熱需求.

Fig.7 Warm up demand of branch predictors in GEM5 simulator and Xiangshan processor圖7 GEM5 模擬器與香山處理器的分支預測器預熱需求
盡管我們努力縮短了負載的預熱時間,但是未能改變整體的仿真時間分布特征.圖2 中少量負載的仿真時長顯著多于其它負載的現象仍然存在.這些檢查點在不恰當地調度下有可能大幅度增加總仿真時間,例如將運行時間較長的多個任務調度到同一個核.因此,合理地調度任務使負載均衡分配非常重要.
然而,在實際系統中,對Verilator 仿真任務的調度比傳統的作業調度更復雜:1)很難預知任務時長;2)Verilator 提供了多線程加速功能,如何在多線程非線性擴展的情況下找到較好的調度策略是個問題;3)多個仿真任務之間存在性能干擾.尤其是2)和3),使得本就是NP-hard 的任務調度問題變得更加復雜.
為了預知任務時長,我們利用profiling 階段在架構模擬器中得到的IPC 來估算仿真任務的周期數作為仿真時間的近似(Verilator 的總仿真時間與周期數正相關).文獻[43]表明,模擬器估算的每秒提交指令數(IPC)與RTL 的真實IPC 可能存在一定差距,但誤差一般在可接受范圍內,并且能較好地反映程序之間每秒提交指令數(IPC)的相對差距[43].這種排序的預測質量可以用歸一化折現累積增益(normalized discounted cumulative gain,NDCG[48])描述.本文用GEM5 模擬器的模擬周期數排序來預測香山處理器的真實RTL 仿真時間排序效果較好,預測結果的NDCG 為0.88(1.0 為完美預測).
針對多線程調度問題,發現在任務時長分布不均時,為長任務開啟多線程可以縮短仿真時間,如圖8 所示,調度2 比調度1 的完成時間更短.如表3所示,各種多線程選項中,系統整體吞吐最高的方案是4 線程.

Table 3 Comparison of Multi-threading Scaling Efficiency of Verilator Emulation When Server Load is Low表3 服務器低負載時Verilator 仿真的多線程擴展效率對比

Fig.8 Impact of enabling multi-threading in Verilator on scheduling policy圖8 開啟Verilator 多線程對調度策略的影響
然而,表3 實驗結果未能考慮任務間的性能干擾.當服務器的全部64 個核都被仿真任務占用時,觀察到了相反的性能數據:8 線程和16 線程下的每核IPS 高于4 線程,這可能與Verilator 巨大的訪存足跡有關[49],而這類訪存足跡巨大的應用會在末級緩存或內存帶寬對鄰居造成干擾[50-55].對比運行單個4 線程任務和滿載運行16 個4 線程任務下的性能計數器,發現滿載時的宿主機進程IPC 比單任務時下降了約66%.
基于表3 和表4 的實驗,將每個64 核服務器劃分為N核的簇(N=8),總共有64/N= 8 個CPU 簇,并以CPU 簇為最小粒度進行調度.雖然,將CPU 核分簇調度不一定能得到全局最優調度,但是在考慮多核和系統干擾時最優調度難以獲得,分簇調度至少是系統效率較高的一種方案.

Table 4 Comparison of Multi-threading Scaling Efficiency of Verilator Emulation When Server is Fully Loaded表4 服務器滿載時Verilator 仿真的多線程擴展效率對比
在利用模擬器IPC 估算仿真時間和將服務器劃分為線程簇的基礎上,任務調度問題可規約為傳統的作業調度問題.雖然要保證圖9(c)的最優調度非常困難(NP-hard)[56-59],但是我們希望避免出現圖9(a)那樣糟糕的調度.因此選擇了LJF.如圖9(b)所示,已有工作證明LJF 的最大完成時間在最差情況下是最優調度的4/3[23-24,59].

Fig.9 Comparison of maximum completion time under different scheduling policies.圖9 不同的調度策略下最大完成時間對比
基于觀察和設計決策,本文提出了HyWarm 框架.HyWarm 分為3 部分:1)預熱需求搜索模塊Warm-Profiler,它會為每個檢查點列出3 段預熱需求區間((圖3).2)功能預熱加速模塊TLWarmer,它基于通用總線協議進行緩存功能預熱.3)并行調度模塊,該部分利用WarmProfiler 得到的IPC 數據估算任務完成時間,以CPU 線程簇為粒度進行LJF 調度.HyWarm 的工作流程如圖10 所示.WarmProfiler 首先會對不同的預熱長度進行嘗試(profiling),以獲得檢查點的全細節預熱長度和功能預熱長度;然后由TLWarmer 進行功能預熱;在功能預熱之后,會根據模擬器的IPC 預測每個負載的仿真時間T,并按照LJF 調度依次運行任務.

Fig.10 Workflow of HyWarm圖10 HyWarm 工作流程
WarmProfiler 要搜索不同的預熱長度以得到如圖6 所示的MPKI 曲線.本文選擇用9(1+N)個樣本點來繪制MPKI 曲線,樣本點的數量可以結合場景進行調整.
關于樣本點的預熱長度選取,在較長的區間選擇幾何級數遞減的預熱長度(100M,50M,25M,10M),在較短的區間采用等差數列遞減的預熱長度(5M,4M,…,1M).我們沒有選擇樣本的預熱區間均勻長度分布(100M,90M,…,10M),這是因為我們發現預熱需求較小的應用占多數,如果采用均勻分布會導致大量的應用落到0~10M 的區間里并會選擇10M 的預熱長度,即使它們的需求只有1M.
在搜索過程中,WarmProfiler 首先用最長預熱長度進行仿真(比如100M 指令)以獲取基準MPKI,然后嘗試尋找能達到MPKI 誤差閾值的最小預熱長度.對余下的8(N)個點,采用二分查找,最多需要運行3lbN 種配置就能找到滿足要求的預熱長度.
圖6 展示了一個樣本點數為5 的搜索過程,假設基準點預熱200M,余下4 個點預熱分別為100M,50M,25M,12.5M.假設MPKI閾值系數為103%.首先測得200M 預熱下的MPKI=1.0;然后嘗試50M 預熱,得到的MPKI=1.04,其值大于MPKI閾值1.03,因此需要嘗試更長的預熱;其次得到100M 預熱下的MPKI=1.01;最終從滿足要求(MPKI<1.03)的點中選擇預熱長度最短的點(100M).該二分查找算法只在MPKI 與預熱長度的函數關系單調遞減時保證選到滿足要求的最短預熱長度.當函數不是單調遞減時,可能會無法選到最短預熱長度,但是不會損失性能準確度.在實踐中發現,大部分應用的MPKI 都是關于預熱長度的單調函數.這與之前的工作中預熱越長MPKI 越低的觀察相符[14,17].
通常情況下,緩存MPKI 曲線與分支預測MPKI相互獨立,因此需要進行2 次WarmProfiler 的搜索過程,分別找到緩存MPKI 飽和點和分支預測MPKI 飽和點.假設緩存MPKI 的飽和預熱長度為CW,分支預測MPKI 的飽和預熱長度為BW.其中緩存預熱可以由功能預熱完成,而分支預測器需要全細節預熱.據此,可以計算出全細節預熱的長度為BW,功能預熱的長度為FW=max(0,CW-BW).在實踐中,因為功能預熱的速度往往比全細節預熱快1~2 個數量級,因此也可以選擇固定的較長的CW(比如100M,200M 等).
TLWarmer 的核心思想是利用像TileLink 這樣的總線協議給二級、三級緩存注入預熱后的緩存內容.注入時,用協議定義的接口向緩存發送訪存請求,并從相應的緩存塊取出緩存.值得討論的是應該發送完整的訪存請求還是經過過濾的訪存請求.
為了完成緩存注入,有2 種技術路線:第1 種路線是發送完整的訪存請求,即按程序順序依次發送所有的訪存指令到緩存中,并由RTL 的緩存替換算法決定留下哪些緩存塊.第2 種路線是用模擬器的替換算法作為過濾器,只將最終留存于緩存中的塊按照LRU 順序注入RTL 緩存中.因為緩存塊的數量一般遠少于訪存請求的數量,可以縮短功能預熱的時間,所以我們選擇了第2 種路線.為了方便起見,本文把第2 種路線命名為Filter 模式.
圖11 展示了Filter 模式下的典型工作流程.首先用功能模擬器生成訪存trace(一般只需20 s 左右即可采集200M 指令的trace),然后在緩存模擬器中重放這些trace,從而使緩存模擬器按某種替換算法留下緩存塊.在緩存模擬器中留存的緩存塊會通過TileLink 協議注入到緩存子系統中,緩存子系統如圖12 所示.注入過程需要RTL 緩存子系統接收并處理128k 個訪存請求(8MB/64B),該過程消耗的時間一般是幾十分鐘.

Fig.11 Workflow of Filter mode圖11 Filter 模式的工作流程

Fig.12 Cache subsystem that receives TileLink requests圖12 接收TileLink 請求的緩存子系統
在完成緩存子系統預熱之后,下一個挑戰是現代處理器的緩存并不是一塊簡單的SRAM,而是需要分bank 和分塊(block)[4,60],導致一塊緩存經常包含幾十個SRAM 實例.為此,我們利用Chisel/Firrtl 實現了自動化的SRAM 轉儲和恢復:首先在Chisel 中選擇需要功能預熱的緩存模塊,并為這些模塊包含的SRAM對象打上標記;然后在Firrtl 中對帶標記的SRAM 對象自動生成轉儲和恢復的代碼;最后當緩存塊注入完成后,緩存子系統的SRAM 中的數據會被轉儲到很多個文件中,然后完整的SoC 啟動時會將這些文件加載到對應的SRAM 中.
本文將64 核處理器核劃分為8 個8 核的CPU 簇,然后在此基礎上對所有任務進行LJF 調度:每完成一個任務,挑選剩下的任務中時長最長的任務運行.為了實現LJF 調度,需要知道任務時長排序,本文用任務的預估仿真周期數排序來替代任務時長排序.任務的預估仿真周期數是根據WarmProfiler 的架構模擬器的IPC 估算的,即預估周期數 等于負載指令數和IPC 相除.
本節介紹HyWarm 帶來的性能評估速度的收益.首先展示WarmProfiler 對SPECCPU?的預熱需求的分析,以及功能預熱能減少的仿真指令數;然后展示檢查點的準確率和仿真時間對比,以證明功能預熱能兼顧準確度和速度;最后展示負載的運行時間分布不均的問題,以及如何通過分簇調度來緩解少數負載仿真時間過長的問題.
1)實驗配置.本文選取的實驗負載是SPECCPU?2006 中用SimPoint 選取的檢查點[10].由于實驗需要測試大量的預熱長度配置,為了縮短測試時間,本文為每一個子項的每一個輸入數據選取權重最大的Sim-Point 檢查點來進行實驗.本文實驗所采用的香山處理器架構配置如表5 所示.重放訪存trace 所使用的緩存模擬器的規格與香山處理器的緩存規格一致[4].

Table 5 Microarchitectural Configuration表5 微結構配置
2)測量指標.本文研究預熱長度時所使用的指標主要包括每條指令周期數(CPI)、一級緩存缺失懲罰(L1MP,一級緩存缺失時等待響應的周期數)、分支跳轉MPKI.其中,L1MP 用于討論緩存預熱效果,BMPKI 用于討論分支預測器預熱效果,CPI 用于討論整體預熱效果.因為在現有的三級緩存實現中較難區分來自二級緩存的demand 請求和預取請求,所以三級緩存MPKI 未被納入對比指標.雖然沒有包含三級緩存MPKI 的數據,但是L1MP 能體現三級緩存中demand miss 帶來的性能損失.
圖13 展示了WarmProfiler 在492 個SPECCPU?檢查點上搜索預熱需求的結果.本文首先統計了每個檢查點的總預熱需求,即取分支預測器預熱需求和緩存預熱需求的較大值.如果沒有WarmProfiler,對所有的檢查點都需要保守地運行100M 指令的預熱.相反地,有了WarmProfiler 的指導,只有19 個檢查點需要100M 預熱和只有47 個檢查點需要50M 預熱.相對于100M 預熱的baseline,WarmProfiler 將總的預熱指令數減少了85.7%.

Fig.13 Distribution of warm up demand (the number of instructions) or checkpoints.圖13 檢查點的預熱需求(指令數)分布
此外,因為TLWarmer 預熱緩存不依賴于全細節預熱,只考慮分支預測器預熱,所以全細節預熱的需求可以被進一步壓縮:只有2 個檢查點需要100M 的全細節預熱和只有9 個檢查點需要50M 的全細節預熱.如果以100M 全細節預熱為基線,總的全細節預熱指令數減少 了95.6%.在WarmProfiler 中,本文借助了GEM5 這樣的架構模擬器來搜索合適的預熱需求.為了驗證GEM5 所獲得的預熱需求是否與RTL的實際預熱需求一致,本文對比了每個子項權重最大的檢查點在GEM5 和RTL 上的預熱需求曲線,并發現當GEM5 的參數與RTL 一致時,GEM5 與RTL的預熱需求的趨勢也較為接近.如圖14 所示,多數子項的模擬器和RTL 的分支預熱需求一致.而像gobmk.trevoc這樣的子項在GEM5 上展示出了比RTL 更長或更短的預熱需求.如果預熱需求預測偏長會導致執行仿真時間增長;而預熱需求預測偏短會導致分支MPKI 偏高.根據本文的實驗結果,預測偏短導致分支MPKI 偏高超0.1 的負載占比為7.5%(4/53),詳細數據在4.3 節給出.

Fig.14 Warm up demand curve of GEM5 simulator and Xiangshan processor圖14 GEM5 模擬器與香山處理器的預熱需求曲線
除此之外,我們還發現了部分應用對預熱長度并不敏感.以緩存為例,通過計算了各個子項的一級緩存缺失懲罰(L1MP)與預熱長度之間的相關性(Pearson’s correlation),在53 個負載中,34 個負載的L1MP 與預熱長度的相關性小于-0.5(我們預期L1MP與預熱長度負相關),但是余下19 個負載沒有顯著的負相關.例如GemsFDTD,lbm,libquantum等負載的L1MP,L2 MPKI 均與預熱長度沒有明顯的相關性,我們將這類負載稱為預熱不敏感應用.在接下來討論預熱效果時,本文僅討論緩存或分支預熱敏感型負載.
本節主要展示了功能預熱和混合預熱能在節約仿真時間的同時兼顧性能準確率.我們主要對比不同方案的仿真完成時間和性能準確率.對比了當性能測量長度為5M 條指令時的多種預熱方案見表6,其中配置X+Y表示長度為X的功能預熱之后進行長度為Y的全細節預熱,Ada 表示根據WarmProfiler 的結果選取的預熱方案,FixedFW(95+5)則是在沒有WarmProfiler 的指導下進行固定長度的功能預熱和全細節預熱.

Table 6 Warm up Configurations表6 預熱配置
圖15 展示了不同預熱方案相對于100M 全細節預熱的L1MP 增幅.實驗結果表明FixedFW (95+5)的混合預熱方案顯著優于0+5 的全細節預熱方案,這體現了功能預熱的有效性.Ada 和FixedFW 部分負載的L1MP 比100M 預熱的基線更低(出現了負值),這可能與替換算法、預取算法有關,因為TLWarmer 只能恢復緩存的SRAM 中的內容,不能恢復預取器和影響塊替換的metadata 的狀態.對一部分負載,這會讓有用的緩存塊更容易留下,而對另一部分負載會讓有用的緩存塊更容易被替換.這也解釋了為什么FixedFW(95+5)的方案無法達到100M 的全細節預熱基線的L1MP.

Fig.15 Impact of different warm up schemes on L1MP圖15 不同預熱方案對L1MP 的影響
從仿真總時間來看,功能預熱的時間取決于需要恢復的緩存塊的個數,一般僅需要5~30 min.得益于此,混合功能預熱方案FixedFW(38.5 h)只需要比0+5 方案(35.8 h)略多的總仿真時間,就能獲得與0+25 相當的緩存預熱效果,見表7.

Table 7 Comparison of Total Simulation Time for Different Functional Warm up Schemes表7 不同功能預熱方案的總仿真時長對比 h
從4.2 節的性能評估結果可以看出,負載的預熱需求往往是隨著負載特征變化的,盲目地選取FixedFW (95+5)的方案實際上無法適應這種變化.而在WarmProfiler 的支持下,可以選擇出對性能評估準確度犧牲較小,同時又節約時間的全細節預熱長度.在圖15、圖16 和圖17 中由WarmProfiler 指導的混合預熱方案被標注為Ada (adaptive),數據點按FixedFW 方案的相對增幅排序.實驗結果表明,自適應混合預熱達到了與0+25 接近的準確率見表8;而所需的總串行仿真時間為54.40 h,僅略大于0+10 方案,見表7.

Table 8 Accuracy Comparison of Different Schemes表8 不同方案準確率對比%

Fig.16 Impact of different warm up schemes on branch MPKI圖16 不同預熱方案對分支MPKI 的影響

Fig.17 Impact of different warm up schemes on CPI圖17 不同預熱方案對CPI 的影響
gamess_cytosine 是一個體現自適應預熱優勢的例子,在使用FixedFW 混合預熱方案時,gamess_cytosine的L1MP,分支MPKI 和CPI 增幅都較大.而Warm-Profiler 的全細節預熱需求很大,即使0+50 的全細節預熱也無法使它的分支MPKI 達到接近0+100 的情況.因此,為了保證準確性,WarmProfiler 直接為gamess_cytosine 選擇了0+100 的預熱方案.在gamess_triazolium上,也看到了類似的現象,WarmProfiler 選擇了75+25的混合預熱方案.
本文將基于模擬器的預熱需求預測和完美預測作了對比,其中完美預測直接利用RTL 進行預熱需求搜索,得到分支預測器預熱飽和點.表9 列出了所有GEM5 預測預熱需求偏低造成MPKI 偏高的負載點(因為更低的MPKI 更接近完整的100M 預熱,所以我們認為MPKI 更低是更準確的表現),其中僅4個負載點遭遇了超過0.1 的分支MPKI 誤差.而根據計算,0.1 的分支MPKI 誤差導致的CPI 誤差一般不超過0.3%.在預熱時間方面,本文的實驗結果表明,模擬器預測的預熱飽和點誤差造成了8.85%的額外仿真時間.作為對比,直接用RTL 進行預熱需求搜索會增加數倍的時間,因此用模擬器預測預熱需求更加高效.

Table 9 Branch MPKI Prediction Error Caused by WarmProfiler (increase)表9 WarmProfiler 的分支MPKI 預測誤差(增高)
雖然本文的方案大幅縮短了預熱所需指令數,但是并不能改變總仿真時間在每個負載上的分布.少數負載仍然因為預熱指令較多、IPC 較低導致仿真周期數顯著長于其他負載.如圖18 所示,檢查點的仿真周期數非常不均衡,如果簡單地讓53 個負載并行地開始仿真,那么仿真的后半段會只剩下幾個最慢的負載.這個問題并不僅存在于自適應預熱方案,負載時長不均衡在普通預熱方案下也存在(見圖5).

Fig.18 Distribution of total detailed simulation cycle counts for 53 workloads using adaptive warm up圖18 使用自適應預熱時53 個負載的全細節仿真周期數分布
2.2 節中的例子定性說明了CPU 多核并行仿真給調度帶來的好處,本文的實驗結果印證了分簇的收益.首先定義了調度均衡度用于描述負載均衡的程度:調度均衡度=平均完成時間/最長完成時間.其次對比了64 核下3 種配置的調度均衡度.如表10 所示,在同樣的負載集下,CPU 簇數量越少,調度均衡度越高,無論是隨機調度還是LJF 調度.這說明CPU簇越少,調度的“難度”越低,越容易達到均衡的調度.而從另一個角度看,LJF 總是能獲得比隨機調度更高的均衡度.在端到端性能對比中,見表11,同樣能看到LJF 的優勢:在多種配置下,LJF 比隨機調度節省了11%~20%的時間.

Table 10 Impact of Cluster Count on Scheduling Balance表10 簇的數量對調度均衡度的影響
為了探究通過架構模擬器的IPC 預測仿真時間帶來的影響,本文對比了通過模擬器預測和先知預測的調度結果(先知預測,即用RTL 的真實IPC 進行LJF 調度).表12 的結果表明模擬器預測對調度結果的影響很小,這是因為GEM5 預測香山處理器仿真時間的NDCG 較高(見2.2 節),非常接近真實仿真時間的排序.

Table 12 Maximum Completion Time of LJF Scheduling Guided by Simulator IPC and Real IPC of RTL表12 采用模擬器IPC 和RTL 的真實IPC 指導LJF調度的最大完成時間h
本節討論3 個設計決策的局限性.
1)在用訪存指令實現功能預熱方面.在此前的體系結構相關工作中,有工作[45]嘗試用訪存時間戳的方式維護一個軟件LRU 緩存,用于功能預熱.實際實現時,除了像本文一樣通過緩存協議注入外,還可以選擇從訪存時間戳生成一系列訪存指令,將需要預熱的緩存塊加載到緩存.在實際操作中,后者具有更好的可遷移性,但是其存在2 方面的問題:一是預熱指令本身會在緩存中留下足跡,影響預熱結果;二是預熱時的訪存并發度依賴于處理器的流水線設計、指令窗口大小、MSHR 數量配置,在比較保守的配置下訪存并發度較低、預熱速度較慢.
2)在功能預熱方面.本文沒有解決分支預測組件的功能預熱問題,因為分支預測組件普遍采用私有接口,并且接口隨架構發生變化.
3)在任務調度方面.本文未展開更細粒度的分簇方式的探索,以及未找到理論最優調度策略.
在技術方面,本文提出了較為通用的RTL 緩存功能預熱解決方案和預熱需求搜索方案.這些方案具有普適性,可以將類似的思路應用于AMBA 協議的緩存和用于其他指令集/微架構處理器.在負載特征刻畫方面,本文指出了當前CPU 仿真的負載運行時長分布嚴重不均的問題,這是因為負載IPC 分布不均、預熱需求分布不均.時長分布嚴重不均導致了要最小化最大完成時間,現階段需要加速的就是仿真指令數最多的應用.因此,未來的工作可以關注如何繼續減少全細節仿真的指令數,以及提高仿真器仿真效率.
作者貢獻聲明:周耀陽完成部分實驗開發任務、整理和分析數據,并撰寫論文;韓博陽、藺嘉煒、王凱帆、張林雋完成部分實驗開發任務;余子濠、唐丹、王卅、孫凝暉、包云崗提供實驗開發思路, 給予工作支持和指導意見.