大話SW26010系列之工欲善其事 必先Benchmark
前言:
SW26010作為國產自主設計的眾核處理器,其峰值浮點運算性能達到了3.06TFlops[1],與英特爾同時期主打的眾核處理 Knights Landing[2]系列十分接近。手握此等神兵利器,誰家超算才是TOP500霸主?現在,讓我們將視線放到TOP500戰場(圖文無關)——
作為兔醬在TOP500戰場的主力, SW26010每個小分隊的64名浮點運算戰士正和人少而強悍的鷹醬KNL大兵在前線酣戰。不消多時,雙方都把隨身攜帶的64KB臨時補給用完了。此時,《Amazing Grace》響起,鷹醬海陸空全方位後期部隊MCDRAM迅速趕到前線完成補給,KNL頓時個個生龍活虎。而兔醬,卻只能遙望山的那頭載著DDR3的DMA卡車正在翻山越嶺——戰鬥進行不下去了,怎麼辦?
苟利國家生死以,豈因禍福避趨之?64戰士憑藉平時在各類極端情況下的高性能陣法訓練,戰士們彼此默契配合,高效地互相傳遞資源共享補給,同行列的戰士們只用了10個cycle就完成了資源共享。而此時,鷹醬的補給也剛好完成……
最後的結果大家也知道了,神威·太湖之光憑藉自主研發的神威SW26010大軍,在兔醬出色的指揮下,一路高歌猛進,榮登TOP500榜首~
以上只是對SW26010性能的一段戲說。那麼,如此強悍且自主研發的眾核處理器,其具體性能架構特性到底如何呢?接下來我們就以benchmarking的方式對SW26010 進行探究。
SW26010處理器的架構如圖1所示。每個SW26010處理器包含4個核組(Core Groups,CG),每個核組包含1個管理核心(Manage Processing Element,MPE)和64個被組織成8x8 mesh的運算核心(Computing Processing Element, CPE)。4個核組的256個CPE一共提供了雙精度2.969TFlops,佔97%以上的性能。因此,我們以CPE為研究對象。
我們以吞吐量(Throughput)和延遲(Latency)為度量,在流水線、訪存、片上通信三方面,結合實驗數據分析闡釋SW26010性能特性及一些有趣的架構特點。其中除主存帶寬測量的stream benchmark之外,其餘benchmark採用彙編實現以儘可能避免不必要的overhead。
一、流水線分析
- 指令延遲:我們構造具有RAW相關性的指令序列進行測量。具體來說,對算術指令,也即$va = op($va, $vb, ...) 的形式,其中$va既是src operand也是dst operand,op代表所測量的指令;對訪存指令,我們採用類似pointer-chasing方式的彙編級實現,也即下一次load的地址源於上一次load進寄存器的值。所得結果如圖2所示。
- 指令吞吐:我們使用每周期指令數(Instruction PerCycle, IPC)作為度量指標。通過逐步增加獨立指令流[4],當IPC不再增加時,吞吐量達到最大且恆定(對於單浮點流水線的SW26010來說,應該達到1)。據此,我們對各類算術指令進行了測算,所得結果如圖3所示。可以發現,對於大多數算術指令,需要7個獨立指令流才能達到最高吞吐。另外,除法和開方指令不僅延遲高,而且只能部分流水,例如雙精度除法需要間隔30個cycle才能發射下一個除法。因此,軟體模擬的除法、開方、倒數開方結合loop unrolling是提升包含這類操作的應用性能的重要途徑。
- 指令發射邏輯:對於順序發射核心,其指令發射順序取決於代碼中指令順序;對於亂序發射核心,當指令操作數及運算單元等所需資源可用時,即可提前發射指令。據此,我們設計了能夠區別這兩類發射邏輯的指令序列,通過測量每次迭代的指令序列運行周期,推斷指令發射邏輯。例如,對於浮點運算指令,我們採用以下指令序列(inst format: op src1, src2, dst):
loop: vmuld $1,$1,$2 #1 vmuld $2,$2,$3 #2 vmuld $4,$4,$1 #3end_loop
由於指令3與指令2無關,與指令1僅存在WAR相關性,因此在亂序發射情況下,3可以在1之後的下一個cycle(back-to-back)發射出去,此時每個迭代平均耗時為7+1=8cycle;而對於順序發射的情況,指令3會在指令2之後的一個cycle發射,導致每次迭代耗時為7+7+1=15cycle。測試發現上述指令序列耗時15cycle/iter,因此可以推斷浮點流水線順序發射。對於訪存流水線,以及兩條流水線間的發射邏輯可以採用類似方法測量,從而得到流水、訪存流水線內順序發射、流水線間亂序的推斷。因此,對於順序發射的浮點流水線,彙編級指令調優尤為重要。
二、訪存性能分析
SW26010 CPE的訪存架構分為三個層次:
- 每核組8GB的主存,通過DMA批量地或者全局load/store離散地訪問。
- 每個CPE上的64KB Scratch-Pad Memory(SPM)。
- 32個64-bit通用寄存器(可擴展為256bit向量寄存器)
對於訪存的帶寬和延遲,我們依據stream[5]和pointer-chasing[6] 方法,採用對應存儲層次的讀寫方法進行benchmarking。
1. SPM訪存性能分析:
單CPE上SPM的Stream測試結果與理論峰值帶寬46.4GB/s(256-bit vector per 4-cycle)具有較大差距,Copy、Scale、Add、Triad帶寬分別是43.74 GB/s, 29.36 GB/s,
31.71 GB/s, 和 30.9 GB/s。研究後我們發現彙編代碼中存在相關指令產生的氣泡、寄存器使用效率低等問題,因此手動對彙編代碼進行調優後,可將Scale、Add、Triad帶寬均提升至40GB/s左右。pointer-chasing結果顯示SPM訪存延遲為2.76ns(~4 cycle)。可以看到,SPM提供的4cycle延遲和40 GB/s帶寬的訪存性能與L1$相當(因此實際上SPM可以配置成軟體模擬的L1$,但這類軟體模擬方法的性能遠不如將其作為可顯式控制的local data memory)。2. 主存性能分析:
- global load性能不佳,尤其是在n個核同時發起global load之後,延遲同核數相關,呈線性增長(~84n cycle),我們完全有理由推斷,多個核心發起global load請求後,這些請求被串列處理了——於是,前線的64個戰士發起後勤補給志願請求後,後勤部門說,你們先排隊吧。結果就是,平均每個CPE的訪存延遲達到了爆炸性的5376個cycle。
- 主存上使用DMA進行Stream Triad實測帶寬僅達到22.6GB/s(4核組共計90.4GB/s),導致Machine Arithmetic Intensity達到了33.84,遠遠高於KNL的7.05。因此,大多數計算核心在SW26010上將嚴重受限於訪存(memory-bound),這也即開篇提到的「後勤補給不足」的問題。圖4的Roofline Model[7]可以直觀的展現這一問題。
三、 片上通信分析
細心的讀者可能發現了,CPE有主存,有類似L1$的私有SPM,有寄存器,卻沒有核間可共享的大Buffer/Cache,那麼,如何緩解低效訪存與高效流水計算的巨大鴻溝?
還記得64戰士們在關鍵時刻的資源互傳共享補給嗎?
這就是SW26010體系結構設計時的「神來之筆」——寄存器通信(Register Level
Communication,RLC)。同行/同列的CPE可以通過陣列網路進行高效的寄存器級別細粒度通信,以實現基於通信的數據共享,從而突破主存帶寬不足的困境。同樣地,我們對RLC進行了通信延遲與帶寬的benchmarking。針對RLC通信延遲,考慮到我們不應預設往返延遲相同,ping-pong test方法並不適合作為測量方法,但可以作為驗證測量結果的有力手段。這裡我們藉助CPE間的同步指令,迫使發送核心等待接收核心接受完數據後再進行下一次發送,從而暴露RLC通信延遲用於測量。我們對同行/列的任意一對CPE進行延遲測試,得到了如圖5的測試結果:
我們發現了一個有趣的現象,即往返延遲不一定相同,其通信延遲與接收方的位置相關,與發射核心的位置無關——也即接收方的位置定了,任意核心發給該核心的RLC通信延遲便確定下來;假如接收方不同,那麼通信延遲可能存在1cycle的差距。整體而言,RLC的10/11cycle(包含發送和接受指令本身的執行延遲)達到了L2$的性能,可以作為高效的數據共享手段。另外,廣播和點對點通信的通信延遲完全一致,似乎可以藉此推斷從核陣列上的RLC通信網路結構:)
對於RLC帶寬,我們通過測量連續多次的流水化RLC延遲以推斷傳輸帶寬。假如RLC可完全流水,我們期待每隔1個cycle便可接收到一個數據,但測量結果告訴我們,事實並非如此。我們發現:假設從核心a到b的單次RLC延遲為L,那麼a從cycle 0開始,連續進行多次RLC之後,b將在第L,L+2, L+4, L+7, L+9, L+11, L+14 … 個cycle接收到數據,也即收到數據的間隔為2,2,3,2,2,3…,於是接收到第n個數據的時間可以表示為: 平均而言,每個2.33個cycle可以接收到連續發射的數據(2333333),因此對於點對點通信,4核組的RLC片上點對點聚合帶寬高達2549 GB/s,廣播聚合帶寬高達4461GB/s。至於RLC無法完全流水的原因,可能是數據需要分塊上網,或者存在其他硬體開銷等,anyway在沒有更多的底層架構資料的情況下,這仍然是個謎,歡迎感興趣的同學繼續深挖。
對於代碼優化而言,RLC通信無法完全流水的這一特點,其實也為我們提供了彙編指令優化的一個小tip:既然無法避免多次RLC引入的額外cycle,那為何不把這些cycle利用起來,多發射一些計算指令,尤其是那些需要在RLC之後執行的指令呢~
因此,綜合benchmarking結果,我們列出如下在SW26010上進行性能優化的建議:
- 大多數應用將受限於訪存,此時性能提升的第一要務是設計適合於RLC的數據共享並行演算法(畢竟連Compute-intensive的GEMM都需要藉助RLC突破訪存瓶頸了,Stencil就不用說了,優化過的kernel中只有arithmetic intensity等於幾百的N-BODY是不需要RLC的一個kernel),最大程度降低對主存的依賴,使流水線得到儘可能及時而充分的後勤補給。這也是SW26010上應用優化最有意思,也最有挑戰性的部分,64戰士們平時訓練的高性能陣法就是這個啦。
- 在突破內存性能瓶頸後(或者應用本身極其compute-intensive),手動彙編調優(提高流水/訪存雙發射、減少氣泡、寄存器重新分配提高利用率等)是提升性能的關鍵(當然,多線程/SIMD等傳統優化手段是優化的基本工作),因為我們的浮點流水線是個乖巧的順序發射流水線。
- 一些其他的trick,例如利用RLC的不完全流水,盡量避免低效的global load/store,使用結合loop unrolling的軟體模擬除法、開方等等。
於上交Sonic Lab科研期間在SW26010上做了一些微小的工作,畢業之際希望做一些分享,很慚愧,謝謝大家。初次撰文,還請大家多多包涵~
參考文獻:
[1] NSCCWX, 「Sunway Taihulight Compiler User Guide,」 2016. [Online]. Available: http://www.nsccwx.cn/
[2] Intel, 「Intel xeon phi processor overview.」 [Online]. Available: https://software.intel.com/en-us/xeon-phi/x200-processor
[3] Xu Z, Lin J, Matsuoka S. Benchmarking SW26010 Many-Core Processor[C]// Parallel and Distributed Processing Symposium Workshops. IEEE, 2017:743-752.
[4] J. Fang, H. Sips, L. Zhang, C. Xu, Y. Che, and A. L. Varbanescu, 「Test-driving intel xeon phi,」 in Proceedings of the 5th ACM/SPEC international conference on Performance engineering. ACM, 2014, pp. 137–148.
[5] J. D. McCalpin, 「Stream: Sustainable memory bandwidth in high performance computers,」 University of Virginia, Charlottesville, Virginia, Tech. Rep., 1991-2007, a continually updated technical report. [Online]. Available: http://www.cs.virginia.edu/stream/
[6] G. Juckeland, S. Borner, M. Kluge, S. Kolling, W. E. Nagel, S. Pflu ?ger, H. Roding, S. Seidl, T. William, and R. Wloch, 「Benchit-performance measurements and comparison for scientific applications.」 in PARCO, 2003, pp. 501–508.
[7] S. Williams, A. Waterman, and D. Patterson, 「Roofline: an insightful visual performance model for multicore architectures,」 Communications of the ACM, vol. 52, no. 4, pp. 65–76, 2009.
推薦閱讀: