文/圖黃博文
ARMPPT中的性能與功耗對比TIPS什麼是亂序多發射?
所謂“多發射”(multiple-issue)指的是處理器在一個時鐘周期内能夠同時執行大于等于兩條指令,“亂序”是亂序執行的簡稱,指的是處理器能夠動态地調度指令,把程序規定必須後置執行、但是實際上并不存在執行沖突的指令提前執行。這兩個結構設計技術需要對整個執行流程進行非常複雜精細的控制和調度,因此亂序多發射被視為是現代高性能處理器微結構的基石。第一代的亂序多發射設計起源于上世紀60年代的超級計算機CDC6600和IBM360/91的中央處理單元。
發射寬度不是一切
作為編号上大于Cortex-72且同屬于Cortex-A7X系列的産品,為什麼A73選擇了雙發射設計?這裡面的原因也頗有意思,首先,Cortex-A73和Cortex-A72雖然編号差距隻有1,卻來自兩個不同的設計團隊。Cortex-A系列的高性能處理器核心由兩個團隊設計,Cortex-A15,Cortex-A57,Cortex-A72這些追求最高性能的IP都來自于ARM的美國德克薩斯州奧斯丁團隊(Intel、NVIDIA、IBM等公司也在德州奧斯丁有類似的CPU設計團隊),而Cortex-A12,Cortex-A17,Cortex-A73來自于ARM在歐洲的設計團隊;其次,從産品路線上看,ARM的歐洲設計團隊追求的目标與美國德州奧斯丁團隊有明顯不同,歐洲團隊追求的不再是極緻性能,而是性能與功耗、面積的一個良好平衡。
在ARM的PPT上我們可以看到,Cortex-A73的功耗性能比進一步下探(意味着性能功耗比的提高),而IPC基本與Cortex-A72持平,通過實現更高的主頻來達到超越Cortex-A73的性能。ARM的官方數據是,将10nm工藝下的Cortex-A73與16nm下的Cortex-A72對比,Cortex-A73的頻率最高可達2.8GHz,性能提高30%,能耗效率提升30%。
可能有人會發出疑問,這可能做到嗎?難道雙發射不是先天劣于三發射或者四發射嗎?
雖然雙發射在發射寬度上确實先天劣于三發射或四發射,實則最終性能并不盡然。發射寬度隻是微結構上衆多重要設計指标中的一個,其他重要設計指标還有很多,例如:
1、分支預測的速度。一般要求極少的周期數就要做出分支指令是否跳轉的判斷,分支預測判斷速度越慢,可能引入的取指令流水線空泡就越多。
2、分支預測準确率。預測準确率直接關系到取上來的指令是否正确,若不正确則需要沖刷流水線,既浪費了功耗也拉低了性能。
3、指令緩存訪問命中率和吞吐量。即便分支預測器快速而準确地指明了指令讀取地址,但是指令緩存如果不能快速供應待取指令,也會拉低性能。
4、寄存器堆的讀寫口數目和共享仲裁。提供多端口并行讀寫能力的寄存器堆是亂序寬發射引擎的核心部件之一。但是多端口的寄存器堆占用面積也較大,在實際設計中經常使用讀寫端口共享的方式來削減所需要的讀寫口數目,這樣一來讀寫口的使用權利仲裁也成為不可忽視的性能設計要素。
5、發射隊列(保留站)的設計。發射隊列同樣是亂序多發射引擎中的核心部件,它的設計有很多可供量化的性能指标,例如項數(深度),框架(多個集中式發射隊列或共享式發射隊列),亦有難以量化的指标,例如發射隊列和其他部件之間的數據前遞(Bypass)網絡等。
6、訪存重排序和地址分析能力。從性能上來說,訪存(包括cache和memory組成的訪存子系統)是非常重要的一個問題,現在的設計一般會将訪存指令也進行亂序執行,但按照内存模型的規定,亂序的訪存必須進行地址的反别名分析(MemoryDisambiguation)來确保執行結果正确。激進的反别名預測可以通過少量可糾正的内存模型違規錯誤來換取可觀的性能提升。
由此可見,發射寬度這個指标隻粗略衡量了核心性能的一部分,因此在市場上我們不難看到同樣的發射寬度而性能差距卻被拉開的例子,例如本文中介紹的亂序雙發射Cortex-A73和亂序雙發射Cortex-A9。同樣地,也有發射寬度更低卻能在IPC上基本打平更高發射寬度的例子,例如亂序雙發射Cortex-A17與亂序三發射Cortex-A15,以及Cortex-A73和Cortex-A72。
那麼這到底是怎麼做的呢?我們來對比分析一下Cortex-A73與Cortex-A72的核心流水線。
ARM展示的官方對比數據
Cortex-A72核心流水線核心流水線變化
讓我們先來看看Cortex-A72的核心流水線部分。Cortex-A72是一個亂序三發射設計,每周期取指令寬度為128比特(意味着4條ARMv8-A指令),每周期解碼寬度為3條指令。ARMv8指令經過解碼以後會打散成粒度更小的微指令(micro-ops或μops),每個周期會把5個微指令分派(Dispatch)給7個發射隊列(IsQ),這意味着Cortex-A72是獨立發射隊列的設計,其中兩個簡單整數操作執行單元前分别配置了一個可保存8條微指令的發射隊列。一個複雜整數操作執行單元前也配置了一個可保存8條微指令的發射隊列,兩條SIMD/浮點操作單元前也分别配置了一個可保存8條微指令的發射隊列,專門處理分支指令的分支執行單元前配置了一個可保存10條微指令的發射隊列,兩個地址生成單元(AGU)分别負責裝載(load)和寫入(store)地址的生成,共享一個可保存16條微指令的發射隊列。以簡單整數操作的流水線長度為度量,約為15級流水。
Cortex-A73對比Cortex-A72做了不少精簡。首先,取指令所需的周期數從5個周期提高到了4個周期,解碼寬度從3條指令降低到了2條指令,但是所需的周期數也從3個周期降低到了1個周期,分派寬度調整為4+2=6個微指令,其中一般整數指令享用4條微指令的分派寬度(Cortex-A73核心流水線圖的中間上半部分)。而SIMD指令和浮點指令在經過額外的解碼周期後,會走一條獨立的2條微指令寬度的分派通道(Cortex-A73核心流水線圖的中間下半部分),呈遞給由兩個SIMD/浮點操作單元共享的一個發射隊列。分派邏輯每個周期最多可以往任意一個發射隊列分派兩條微指令。整數執行單元集群也有所調整,主要表現為:
1、執行單元的通用化。例如Cortex-A72中簡單整數執行單元與複雜整數執行單元是獨立的,但Cortex-A73中是整合的,Cortex-A73中的兩個整數執行單元既能執行簡單整數操作也能執行複雜整數操作,其中一個可以執行整數乘法,另一個可以執行整數除法。此外,Cortex-A73的地址生成單元也不再區分裝載和寫入,兩個地址生成單元都能夠執行裝載和寫入。
2、發射隊列的共享化。Cortex-A73的發射隊列多為兩個執行單元共享,例如兩個整數執行單元共享一個發射隊列,兩個地址生成單元共享一個發射隊列,兩個SIMD/浮點執行單元共享一個發射隊列。對比Cortex-A72來看,Cortex-A72更加獨立的發射隊列設計有利于提高容量利用率,但如果發射隊列容量不夠的話也容易導緻性能減退。
以“Cortex-A73核心流水線”圖中執行周期最短的分支指令計算,Cortex-A73的核心流水線深度也縮減為11~12級。另一個值得注意的趨勢是,ARM的默認一級指令緩存大小一直在提高,Cortex-A15的默認一級指令緩存大小為32KB,Cortex-A57和Cortex-A72都改為48KB,Cortex-A73則改為64KB,并且使用了4路組關聯,64字節的Cache字塊粒度。
在先前的設計中,即便指令讀取前端正确預測了指令流走向并且指令緩存也以最大吞吐量提供了數據(意味着每一個bank/subbank都沒有停頓),在指令分解成微指令時仍有流水空泡産生。ARM聲稱在Cortex-A73核心中引入了提前檢測這種氣泡是否産生的能力,并在出現這種情況時提前解碼微指令避免産生氣泡。這一設計的特征與Intel的uopscache比較吻合,筆者據此猜測這裡可能引入了類似于uopscache的設計。
在分支預測上,Cortex-A73使用了更加先進的分支預測器,分支目标地址緩存(BTAC)更大,這一結構通常被用來加快分支預測的判斷速度。一般來說,分支預測器使用的各種表結構做得越大,可以保存的分支曆史信息越多,分支指令的預測幹擾就越少,因此分支預測準确率就越高,IPC就越高。但是當表項結構做得太大時,訪問記錄表所需的時間也會拉長,由此延長了分支預測的決斷時間,因此對性能是有害的。在一定程度内提高記錄表大小,但同時控制住分支曆史記錄表的訪問周期數不至于延長時,IPC會得益于分支預測準确率而提高,但是如果分支曆史記錄表的訪問周期數被延長,IPC就會有跳水式的下跌。
Cortex-A73核心流水線
180nm和100nm工藝下,分支曆史記錄表的大小與IPC的關系為了同時提高分支預測所需記錄表的大小,同時又縮短訪問延遲、從而控制分支預測所需時間,一般處理器微結構中會使用如同多級高速緩存一樣的多級記錄表。通常第一級記錄表容量較小但速度很快,保存最常用的記錄,而後級記錄表就做得比較大,保存盡可能多的記錄。Cortex-A73也使用了一樣的設計思路,其分支目标地址緩沖區使用了多級設計,第一級僅能保存64條分支目标地址記錄,值得一提的是ARM在Cortex-A72中也使用了”micro-BTB”的描述,這暗示着Cortex-A72的BTB也使用了多級結構。對比Cortex-A17,Cortex-A73中也引入了新增的間接分支預測器,據稱為2路組關聯*256項的組成結構,但缺失其他相關信息的情況下,暫不清楚這個間接分支預測器與Cortex-A72中的設計有何不同。
在寄存器重命名的方法上,ARM聲稱進行了“亂序執行方法的哲學性改變”,這指的是使用了基于物理寄存器堆的寄存器重命名方法。這一改變對于ARM來說确實是一個可以值得誇耀的進步,但是AMD早已經于第一代推土機(Bulldozer)架構、Intel已經于2010年的SandyBridge架構轉向了物理寄存器堆的設計。所以這一設計對于業界來說已經不能算是前沿,更多的是ARM作為高性能先進微結構設計的後來者補上了又一個空缺。先前Intel一直使用着基于數據複制的寄存器重命名方法,這一做法的好處是成熟而實現簡單,其曆史可以追溯到上世紀60年代的超級計算機IBMSystem360/91上。但其壞處也顯而易見,就是數據搬移的功耗。在64位指令集中一個普通數據的複制就意味着64位的複制,當Intel在SandyBridge上引入AVX這種SIMD指令集時,這一缺憾就再也不能忍了,而物理寄存器堆的好處是,整個亂序執行引擎中隻要對每個數據保留一個副本即可,而且移動數據時隻需要移動物理寄存器堆的指針,這樣就大大減少了移動數據的功耗開銷。
綜上,經過精簡加強的Cortex-A73核心能夠在相同工藝的前提下實現25%的核心面積縮減,達到與Cortex-A53類似的核心面積水平。
TIPS分支指令的預測幹擾(Interference)
所有的分支預測器都依賴于保存分支指令的曆史記錄進行預測。例如,當某個分支指令發生跳轉/不跳轉時,分支曆史記錄表中就會記錄這一信息,如果發生連續的跳轉/不跳轉,就可以認為這一分支具有明顯的偏向性,分支預測器就會據此做出預測。但是程序執行周期中會碰到的動态分支指令數是一個天文數字,而底層受限于物理限制,分支曆史記錄表不可能做到無限大,于是就會出現許多分支指令共享分支曆史記錄表中的一個表項的情況,這個情況下就會出現相互幹擾,導緻預測失準。經典的一個反幹擾技巧是在索引分支曆史記錄表時使用哈希(hash)函數将分支記錄盡量散開到表中的不同位置,這一技巧最早發表于上世紀90年代,目前已經應用于各大主流處理器微結構當中。
訪存子系統
訪存子系統的改變從load/sotrebuffer就開始了。ARM聲稱Cortex-A73的load/storebuffer可以動态地檢測指令發射模式,并且在發生一些特定事件時動态改變指令發射策略。例如檢測到流訪存(stream)模式時,store操作就會以最快的速率發射出去,這一做法可能是為了方便執行後端在一級緩存層面,或者是更下層的二級緩存、一緻性單元部分做寫合并來縮減帶寬需求。
在TLB上,ARM為Cortex-A73的主TLB加上了面對流訪存的預取器,這樣一來在流訪存跨越頁邊界時,主TLB早已準備好了新的TLB表項,保證TLB在這種場景下不發生缺失。Cortex-A73的TLB現在支持2個同時處理的TableWalk。并且提供了非阻塞式訪問的能力,在進行TableWalk時TLB還能夠繼續接受其他請求并能夠輸出TLB命中。
在一級緩存上,ARM終于從物理索引+物理标記(PIPT)的設計改成了虛拟索引+物理标記(VIPT)。在介紹TLB時我們曾提到,理論上每一次訪問高速緩存都需要進行虛拟地址到物理地址的轉換,比較慢但是同時也比較穩妥的做法是,等待虛拟地址翻譯到物理地址的過程完成後再訪問高速緩存,這樣一來就拉長了高速緩存的訪問路徑,提高了命中延遲,對性能有害。能不能使用虛拟地址直接訪問高速緩存呢?答案是可以,這種設計被稱為虛拟索引+虛拟标記,但使用這種設計需要非常小心,因為虛拟地址是可以重複的,這會帶來内存地址别名問題導緻程序甚至整個系統崩潰。同時兼顧物理索引+物理标記的穩妥,和虛拟索引+虛拟标記的性能,就是虛拟索引+物理标記(VIPT)。這種設計利用了頁面偏移和頁号編碼與高速緩存地址索引有部分重疊的特性,在高速緩存内部使用物理地址作為對比标記(Tag),但訪問高速緩存時使用虛拟地址索引躲開TLB的延遲,在高速緩存的标記陣列訪問完畢,輸出了一整組高速緩存的地址标記後,TLB的虛實地址轉換也并行地完成了,就能夠在不産生内存地址别名的情況下快速判斷高速緩存是否命中。
Cortex-A73的一級和二級緩存都配備了獨立的預取器,并且比ARM先前的設計支持更大的預取步長。ARM聲稱這一預取器可以幫助Cortex-A73在流式訪存下獲取接近理論最大值的帶寬。Cortex-A73的二級緩存最大可配置為8MB大小,為Cortex-A72的兩倍,同時Cortex-A73的二級緩存為包含式設計,這種設計能夠簡化多核心處理器下的緩存一緻性處理,但是也會帶來緩存數據副本的問題,亦即二級緩存始終包含上層一級緩存的數據,使得緩存空間被浪費,如果是嚴格包含式設計的話,還會出現多核心互相幹擾的問題,例如核心1占用了一塊二級緩存,導緻二級緩存把核心2保存在此處的數據替換掉時,由于嚴格包含式設計的規定,二級緩存必須通知核心2把一級緩存中的數據也丢棄掉,這就會造成性能損失。
結論分析
雖然Cortex-A73從3發射降級到2發射,但是通過加強其他方面,ARM聲稱它的SPEC性能将與Cortex-A72近似,同時在BBench上同頻性能提高近10%,使用FFMPEG編碼器測試的NEONSIMD性能提高5%(Cortex-A73的下一代會提高更多),使用64位模式的JMC流複制測試的訪存性能提高15%,而功耗下降20%。
值得一提的是,在Cortex-A35中首次引入的硬件功耗狀态管理也在Cortex-A73上出現了。此前的設計方案使用粗粒度的軟件管理,但絕大部分廠商并不買賬,如果ARM這一次推行Cortex-A73的硬件功耗狀态管理能夠成功形成影響力的話,其動态功耗還能夠進一步下降。
ARM聲稱使用Cortex-A73作為主核心的SoC在今年年末前就能見諸市場,這個核心如果真的能夠做到ARMPPT上發布的數字的話,将會給其他通過指令集授權來開發自研核心的廠商如高通的貓鼬Kyro和三星的金環蛇Mongoose帶來更大壓力。縮減了發射寬度的Cortex-A73能否從Cortex-A72手中扛過大旗,讓我們拭目以待。
TIPSTLB是什麼?
現代的計算機系統通常使用虛拟内存。虛拟内存和物理内存地址的轉換就是通過頁表進行,而頁表一般放在内存中由操作系統維護。理論上每一次訪問高速緩存都需要頁表的介入進行地址翻譯,如果每一次訪問都去内存裡面取用頁表就太慢了,于是TLB應運而生,TLB實際上是頁表翻譯在處理器内部的緩存,處理器無需訪問内存就能夠知道一些常用虛拟地址對應的物理地址,大大加快了翻譯速度。
同工藝同頻率的Cortex-A73與Cortex-A72性能對比