加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
    • 一、緩存Cache
    • 二、超標(biāo)量
    • 三、亂序執(zhí)行
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

深入了解汽車系統(tǒng)級(jí)芯片SoC連載之四:緩存、超標(biāo)量、亂序執(zhí)行

2022/03/04
1829
閱讀需 32 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

一、緩存Cache

我們看到CPU參數(shù)經(jīng)常會(huì)提到1、2、3級(jí)緩存容量,有時(shí)還有L1$的標(biāo)識(shí),這是什么呢。

TLB與兩級(jí)緩存

資料來源:互聯(lián)網(wǎng)

緩存(Cache)是指訪問速度比一般隨機(jī)存取存儲(chǔ)器(RAM)快的一種高速存儲(chǔ)器,通常緩存不像系統(tǒng)主存那樣使用DRAM技術(shù),而使用昂貴但較快速的SRAM技術(shù)。

緩存的工作原理是當(dāng)CPU要讀取一個(gè)數(shù)據(jù)時(shí),首先從CPU緩存中查找,找到就立即讀取并送給CPU處理;沒有找到,就從速率相對(duì)較慢的內(nèi)存中讀取并送給CPU處理,同時(shí)把這個(gè)數(shù)據(jù)所在的數(shù)據(jù)塊調(diào)入緩存中,可以使得以后對(duì)整塊數(shù)據(jù)的讀取都從緩存中進(jìn)行,不必再調(diào)用內(nèi)存。

正是這樣的讀取機(jī)制使CPU讀取緩存的命中率非常高(大多數(shù)CPU可達(dá)90%左右),也就是說CPU下一次要讀取的數(shù)據(jù)90%都在CPU緩存中,只有大約10%需從內(nèi)存讀取。這大大節(jié)省了CPU直接讀取內(nèi)存的時(shí)間,也使CPU讀取數(shù)據(jù)時(shí)基本無需等待。

總體而言,CPU讀取數(shù)據(jù)的順序是先緩存后內(nèi)存。

 一級(jí)緩存即L1 Cache,因?yàn)镃ache的發(fā)音與英語現(xiàn)金Cash的發(fā)音相同,因此有時(shí)寫做L1$。一級(jí)緩存分指令和數(shù)據(jù),二級(jí)緩存即L2 Cache,不分指令和數(shù)據(jù)。一級(jí)緩存是每個(gè)核獨(dú)有,少量多核如12核以上二級(jí)緩存是4個(gè)或多個(gè)核共享,大部分二級(jí)緩存是每個(gè)核獨(dú)有的,三級(jí)緩存即L3 Cache是通過總線與內(nèi)核連接的,是多個(gè)核共用的。

因?yàn)榫彺媸褂肧RAM,其晶體管密度低,所占面積大,這就意味著成本高,簡單地說,緩存用的越多,成本就越高,性能就越強(qiáng)。Cache存儲(chǔ)數(shù)據(jù)是固定大小為單位的,稱為一個(gè)Cache entry,這個(gè)單位稱為Cache line或Cacheblock。給定Cache容量大小和Cache line size的情況下,它能存儲(chǔ)的條目個(gè)數(shù)(number of cache entries)就是固定的。因?yàn)镃ache是固定大小的,所以它從DRAM獲取數(shù)據(jù)也是固定大小。對(duì)于X86來講,它的Cache line大小與DDR3、4一次訪存能得到的數(shù)據(jù)大小是一致的,即64Bytes。

通常L1 Cache離CPU核心需要數(shù)據(jù)的地方更近,而L2 Cache則處于邊緩位置,訪問數(shù)據(jù)時(shí),L2 Cache需要通過更遠(yuǎn)的銅線,甚至更多的電路,從而增加了延時(shí)。 

L1 Cache分為ICache(指令緩存)和DCache(數(shù)據(jù)緩存),指令緩存ICache通常是放在CPU核心的指令預(yù)取單元附近的,數(shù)據(jù)緩存DCache通常是放在CPU核心的load/store單元附近。而L2 Cache是置于CPU pipeline之外的。還有L3緩存,通常是多核共享的緩存,容量更大。

緩存是逐級(jí)的,1級(jí)緩存中找不到,就到2級(jí)緩存里找,然后是3級(jí),最后是芯片外的存儲(chǔ)器。 由于內(nèi)存種類多,需要引入內(nèi)存管理單元,即MMU。MMU是硬件設(shè)備,它被保存在主存(main memory)的兩級(jí)頁表控制,MMU的主要作用是負(fù)責(zé)從CPU內(nèi)核發(fā)出的虛擬地址到物理地址的映射,并提供硬件機(jī)制的內(nèi)存訪問權(quán)限檢查。MMU使得每個(gè)用戶進(jìn)程擁有自己的地址空間,并通過內(nèi)存訪問權(quán)限的檢查保護(hù)每個(gè)進(jìn)程所用的內(nèi)存不被其他進(jìn)程破壞。

處理器引入MMU后,讀取指令、數(shù)據(jù)需要訪問兩次內(nèi)存:首先通過查詢頁表得到物理地址,然后訪問該物理地址讀取指令、數(shù)據(jù)。為減少因MMU導(dǎo)致的處理器性能下降,引入了TLB,TLB是Translation Lookaside Buffer的簡稱,可翻譯為“地址轉(zhuǎn)換后緩沖器”,亦簡稱為“快表”。簡單地說,TLB就是頁表的Cache,其中存儲(chǔ)了當(dāng)前最可能被訪問到的頁表項(xiàng),其內(nèi)容是部分頁表項(xiàng)的一個(gè)副本。只有在TLB無法完成地址翻譯任務(wù)時(shí),才會(huì)到內(nèi)存中查詢頁表,這樣就減少了頁表查詢導(dǎo)致的處理器性能下降。

什么是頁表(Page Table)

這是操作系統(tǒng)里的一個(gè)術(shù)語,操作系統(tǒng)的一個(gè)主要任務(wù)是將程序彼此隔離。因此需要建立不同的內(nèi)存空間,也就是需要給內(nèi)存安排不同的地址。頁表通常是操作系統(tǒng)決定的。對(duì)于32位操作系統(tǒng),如果想支持32位的操作系統(tǒng)下的4GB進(jìn)程虛擬地址空間,假設(shè)頁表大小為4K,則共有2的20次方頁面。

如果采用速度最快的1級(jí)頁表,對(duì)應(yīng)則需要2的20次方個(gè)頁表項(xiàng)。一個(gè)頁表項(xiàng)假如4字節(jié),那么一個(gè)進(jìn)程就需要(1048576*4=)4M的內(nèi)存來存頁表項(xiàng)。這太大了,成本太高,因此需要分級(jí),采用2級(jí)頁表,則創(chuàng)建進(jìn)程時(shí)只需有一個(gè)頁目錄就可以了,占用(1024*4)=4KB的內(nèi)存。剩下的二級(jí)頁表項(xiàng)只有用到的時(shí)候才會(huì)再去申請(qǐng)。若是64位,則需要4級(jí)頁表,Linux在v2.6.11以后,最終采用的方案是4級(jí)頁表,分別是:

PGD:Page Global Directory (47-39), 頁全局目錄

PUD:Page Upper Directory (38-30),頁上級(jí)目錄

PMD:Page Middle Directory (29-21),頁中間目錄

PTE:Page Table Entry (20-12),頁表項(xiàng)

對(duì)于任何一條帶有地址的指令,其中的地址應(yīng)該認(rèn)為是虛擬內(nèi)存地址而不是物理地址。假設(shè)寄存器a0中是地址0x1000,那么這是一個(gè)虛擬內(nèi)存地址。虛擬內(nèi)存地址會(huì)被轉(zhuǎn)到內(nèi)存管理單元(MMU,Memory Management Unit)并翻譯成物理地址。之后這個(gè)物理地址會(huì)被用來索引物理內(nèi)存,并從物理內(nèi)存加載,或者向物理內(nèi)存存儲(chǔ)數(shù)據(jù)。從CPU的角度來說,一旦MMU打開了,它執(zhí)行的每條指令中的地址都是虛擬內(nèi)存地址。為能夠完成虛擬內(nèi)存地址到物理內(nèi)存地址的翻譯,MMU會(huì)有一個(gè)表單,表單中,一邊是虛擬內(nèi)存地址,另一邊是物理內(nèi)存地址。

分頁技術(shù)的核心思想是將虛擬內(nèi)存空間和物理內(nèi)存空間視為固定大小的小塊,虛擬內(nèi)存空間的塊稱為頁面(pages),物理地址空間的塊稱為幀(frames),每一個(gè)頁都可以映射到一個(gè)幀上。每個(gè)page創(chuàng)建一條表單條目,所以每一次地址翻譯都是針對(duì)一個(gè)page。而RISC-V中,一個(gè)page是4KB,也就是4096Bytes。對(duì)于虛擬內(nèi)存地址,我們將它劃分為兩個(gè)部分,index和offset,index用來查找page,offset對(duì)應(yīng)的是一個(gè)page中的哪個(gè)字節(jié)。當(dāng)MMU在做地址翻譯的時(shí)候,通過讀取虛擬內(nèi)存地址中的index可以知道物理內(nèi)存中的page號(hào),這個(gè)page號(hào)對(duì)應(yīng)了物理內(nèi)存中的4096個(gè)字節(jié)。之后虛擬內(nèi)存地址中的offset指向了page中的4096個(gè)字節(jié)中的某一個(gè),假設(shè)offset是12,那么page中的第12個(gè)字節(jié)被使用了。將offset加上page的起始地址,就可以得到物理內(nèi)存地址。

頁表是存在內(nèi)存里的。那就是一次內(nèi)存I/O光是虛擬地址到物理地址的轉(zhuǎn)換就要去內(nèi)存查4次頁表,再算上真正的內(nèi)存訪問,最壞情況下需要5次內(nèi)存I/O才能獲取一個(gè)內(nèi)存數(shù)據(jù),這太費(fèi)時(shí)間,也導(dǎo)致功耗增加,于是TLB誕生了,TLB就是頁表緩存。 

當(dāng)CPU執(zhí)行機(jī)構(gòu)收到應(yīng)用程序發(fā)來的虛擬地址后,首先到TLB中查找相應(yīng)的頁表數(shù)據(jù),MMU從TLB中獲取頁表,翻譯成物理地址,如果TLB中正好存放著所需的頁表,則稱為TLB命中(TLB Hit),接下來CPU再依次看TLB中頁表所對(duì)應(yīng)的物理內(nèi)存地址中的數(shù)據(jù)是不是已經(jīng)在一級(jí)、二級(jí)緩存里了,若沒有則到內(nèi)存中取相應(yīng)地址所存放的數(shù)據(jù)。如果TLB中沒有所需的頁表,則稱為TLB失?。═LB Miss),接下來就必須訪問物理內(nèi)存中存放的頁表,同時(shí)更新TLB的頁表數(shù)據(jù)。 TLB也分指令和數(shù)據(jù)。

 典型架構(gòu)Cortex-A78緩存指令流程

圖片來源:ARM

MOP緩存是一些經(jīng)過預(yù)處理指令的融合操作緩存。

二、超標(biāo)量

早期的計(jì)算機(jī)都是串行計(jì)算,隨著對(duì)吞吐量需求越來越高,并行計(jì)算出現(xiàn)了。常見的并行計(jì)算有三種指令并行、數(shù)據(jù)并行和任務(wù)并行。任務(wù)并行更多借助軟件才能實(shí)現(xiàn)。對(duì)硬件來說有指令并行(ILP)、線程并行和數(shù)據(jù)并行三種。 

指令級(jí)并行是一種隱式并行,對(duì)用戶來說是完全透明的,用戶完全看不到也感覺不到,也就是寫程序的人不需要關(guān)注,通過流水線和超標(biāo)量,使得一個(gè)程序的指令序列中有多條同時(shí)亂序運(yùn)行,順序提交。這依賴寄存器重命名、多個(gè)執(zhí)行單元、重排序緩沖和指令預(yù)測技術(shù)。 

線程級(jí)并行是一種顯式并行,對(duì)用戶來說不透明,也就是說程序員要寫多線程程序。線程級(jí)并行主要指同時(shí)多線程(SMT)或超線程(HT)以及多核和多處理器。SMT是在指令級(jí)并行的基礎(chǔ)上的擴(kuò)展,可以在一個(gè)核上運(yùn)行多個(gè)線程,多個(gè)線程共享執(zhí)行單元,以便提高部件的利用率,提高吞吐量。SMT需要為每個(gè)線程單獨(dú)保持狀態(tài),如程序計(jì)數(shù)器(PC)、寄存器堆、重排序緩沖等。 數(shù)據(jù)級(jí)并行是一種顯式并行,主要指單指令多數(shù)據(jù)(SIMD),比如a,b和c都是相同大小的數(shù)組,要進(jìn)行的計(jì)算是a的每一個(gè)元素與b的響應(yīng)元素進(jìn)行運(yùn)算,結(jié)果放入c的對(duì)應(yīng)元素中。如果沒有SIMD,就需要寫一個(gè)循環(huán)執(zhí)行多遍來完成,而SIMD中一條指令就可以并行地執(zhí)行運(yùn)算。

線程的概念就是程序的執(zhí)行序,每個(gè)執(zhí)行序有執(zhí)行上下文需要保存。 傳統(tǒng)的通用處理器都是標(biāo)量處理器,一條指令執(zhí)行只得到一個(gè)數(shù)據(jù)結(jié)果。但對(duì)于圖像、信號(hào)處理等應(yīng)用,存在大量的數(shù)據(jù)并行性計(jì)算操作,這些數(shù)據(jù)都具備方向,一般稱為向量計(jì)算。 

超標(biāo)量(Superscalar)是指在CPU中有一條以上的流水線,并且每時(shí)鐘周期內(nèi)可以完成一條以上的指令,這種設(shè)計(jì)就叫超標(biāo)量技術(shù)。其實(shí)質(zhì)是以空間換取時(shí)間。而超流水線是通過細(xì)化流水、提高主頻,使得在一個(gè)機(jī)器周期內(nèi)完成一個(gè)甚至多個(gè)操作,其實(shí)質(zhì)是以時(shí)間換取空間。

超標(biāo)量CPU的工作流程如下:

(1)Fetch(取指令):這部分負(fù)責(zé)從I-Cache中取指令,I-Cache負(fù)責(zé)存儲(chǔ)最近常用的指令;分支預(yù)測器用來決定下一條指令的PC值。

(2)Decode(解碼):識(shí)別指令的類型

(3)RegisterRenaming(寄存器重命名):解決WAW和WAR這兩種“偽相關(guān)性”,需要使用寄存器重命名的方法,將指令集中定義的邏輯寄存器重命名為處理器內(nèi)部使用的物理寄存器。物理寄存器的個(gè)數(shù)更多于邏輯寄存器,處理器可以調(diào)度更多可以并行執(zhí)行的指令。將存在RAW的寄存器進(jìn)行標(biāo)記,后續(xù)通過旁路網(wǎng)絡(luò)(bypassing network)解決存在的“真相關(guān)性”。

(4)Dispatch(分發(fā)):被重命名之后的指令會(huì)按照程序中的規(guī)定順序,寫到發(fā)射隊(duì)列(Issue Queue)、重排序緩存(ROB)和Store Buffer等部件中

(5)Issue(發(fā)射):經(jīng)過流水線的分發(fā)(Dispatch)階段之后,指令被寫到了發(fā)射隊(duì)列(Issue Queue)中,仲裁(select)電路回從這個(gè)部件中挑選出合適的指令送到FU中執(zhí)行。

(6)RegisterFile Read(讀取寄存器):被仲裁電路選中的指令需要從物理寄存器堆(Physical Register File,PRF)中讀取操作數(shù)

(7)Execute(執(zhí)行):各種FU單元執(zhí)行

(8)Writeback(寫回):將FU計(jì)算的結(jié)果寫到物理寄存器(PRF)中,通過旁路網(wǎng)絡(luò)將計(jì)算結(jié)果送到需要的地方。

(9)Commit(提交):這個(gè)階段起主要作用的部件是重排序緩存(ROB),它將亂序執(zhí)行的指令拉回到程序中規(guī)定的順序。

目前絕大多數(shù)CPU都是超標(biāo)量結(jié)構(gòu)。

ARMNeoverse V1的微架構(gòu)

圖片來源:ARM

上圖是ARM Neoverse V1的架構(gòu),是目前ARM面向服務(wù)器領(lǐng)域最強(qiáng)的計(jì)算架構(gòu)。對(duì)于一個(gè)內(nèi)核架構(gòu)來說,通常分為三部分:前端、執(zhí)行引擎和存儲(chǔ)系統(tǒng),其中前端是著墨最多的地方,也是變化最多的地方。

圖中解碼器為5路,V1架構(gòu)最高可擴(kuò)展到8路,也就是IPC為8。這是目前最高的IPC。ARM架構(gòu)的CPU增加性能最簡單的方法就是提高IPC。

每增加一路解碼器,系統(tǒng)的復(fù)雜程度就會(huì)大大增加,在內(nèi)核前端部分,解碼器所占的面積最大,也就是占芯片成本比例最高,要保障成本不大幅度增加同時(shí)提升性能,就需要先進(jìn)的芯片制造工藝,盡量提高晶體管密度,在有限的面積內(nèi)塞入更多的晶體管。ARM架構(gòu)的升級(jí)和芯片制造工藝的升級(jí)是相輔相成的,沒有先進(jìn)制造工藝,ARM架構(gòu)的芯片性能提升也帶來成本大幅度提升,沒有ARM架構(gòu)的升級(jí),先進(jìn)制造工藝也無用武之地。

流水線是為了提高時(shí)鐘頻率,將每個(gè)步驟再細(xì)分,分的越細(xì),每一級(jí)執(zhí)行的時(shí)間就越短,運(yùn)行頻率就可以提高。

但流水線并非越深越好。

(1)每一級(jí)流水線均由寄存器組成,更多的流水線級(jí)數(shù)意味著消耗更多的寄存器,產(chǎn)生更大的面積開銷,功耗也會(huì)增大,成本也會(huì)上升。

(2)每一級(jí)流水線需要握手,流水線的最后一級(jí)反壓信號(hào)可能會(huì)一直串?dāng)_到最前一級(jí)造成嚴(yán)重的時(shí)序問題。

(3)流水線的取指階段得知條件跳轉(zhuǎn)的結(jié)果是到底跳還是不跳,因此只能進(jìn)行預(yù)測,而到了流水線的末端才能通過實(shí)際運(yùn)算得知該分支是真的該跳還是不該跳。如果發(fā)現(xiàn)真實(shí)的結(jié)果與預(yù)期的結(jié)果不一致,意味著預(yù)測失敗,需要將所有的預(yù)取指令全部丟失。流水線越深,則意味著浪費(fèi)和損失越嚴(yán)重;流水線越淺,則浪費(fèi)和損失越少。

三、亂序執(zhí)行

超標(biāo)量CPU最典型特性就是亂序執(zhí)行,Out-of-Order Execution,簡稱OoOE或OOE。超標(biāo)量CPU會(huì)處理多種算法,因?yàn)椴煌噶畹倪\(yùn)算周期數(shù)不同,例如乘法運(yùn)算所需的時(shí)間周期就比加法運(yùn)算長很多,所以如果一個(gè)需要很長時(shí)間的指令后面緊跟著需要使用其結(jié)果的指令的話,就會(huì)浪費(fèi)很多時(shí)間,所以打亂指令的執(zhí)行順序就很重要。

針對(duì)亂序執(zhí)行有不少的算法,但是歸根到底都是以保留棧為基礎(chǔ)進(jìn)行設(shè)計(jì)的。保留棧的核心思想,是把譯碼完成后的指令根據(jù)各自的指令種類,將譯碼后的指令送往各自的保留棧中保存下來,如果該指令所有操作數(shù)都已準(zhǔn)備齊全,則可以開始進(jìn)行亂序發(fā)射。注意,執(zhí)行可以亂序,但提交不可以,否則就出現(xiàn)錯(cuò)誤了。 

在處理器中,先后執(zhí)行的指令之間經(jīng)常具有相關(guān)性(例如后一條指令用到前一條指令向寄存器寫入的結(jié)果),因此早期簡單的處理器使后續(xù)指令停頓,直到其所需的資源已經(jīng)由前序指令準(zhǔn)備就緒。

Tomasulo算法則通過動(dòng)態(tài)調(diào)度的方式,在不影響結(jié)果正確性的前提下,重新排列指令實(shí)際執(zhí)行的順序(亂序執(zhí)行),這種算法是1966年Robert Tomasulo 發(fā)明,沿用至今。該算法使用了寄存器重命名機(jī)制。

指令之間具有數(shù)據(jù)相關(guān)性(例如后條指令的源寄存器恰好是前條指令要寫入的目標(biāo)寄存器),進(jìn)行動(dòng)態(tài)調(diào)度時(shí)必須避免三類冒險(xiǎn)(即流水線停頓):寫后讀(Read-after-Write, RAW)、寫后寫(Write-after-Write, WAW)、讀后寫(Write-after-Read, WAR)。

第一種冒險(xiǎn)也被稱為真數(shù)據(jù)相關(guān)(True Data Dependence),而后兩種冒險(xiǎn)稱為偽相關(guān),偽相關(guān)并不一定導(dǎo)致流水線停頓,它們可以由寄存器重命名來予以解決,亂序執(zhí)行的關(guān)鍵就是識(shí)別偽相關(guān)。 寄存器重命名有兩種,一種就是將一體系架構(gòu)寄存器ARF(Architected Register File)動(dòng)態(tài)映射到一個(gè)專門的物理寄存器堆PRF(Physical Register File)上,消除WAW和WAR冒險(xiǎn)。

由一個(gè)Mapping Table負(fù)責(zé)管理和查詢,這個(gè)重命名的過程對(duì)用戶透明,用戶只能看到ARF。讀出指令和動(dòng)作后先把這些都保存在保留站(Reservation Stations)中,然后CDB(公共數(shù)據(jù)總線)上進(jìn)行廣播,看這個(gè)計(jì)算結(jié)果有沒有作為是其他指令源操作數(shù)的。如果保留站發(fā)現(xiàn)有,就會(huì)更新保留站源操作數(shù)的值。這樣就代替了流水線寄存器。這種辦法有可能出現(xiàn)不按順序提交,因此無法實(shí)用。八十年代后對(duì)算法做了改進(jìn),增加了ROB(Reorder Buffer),在Tomasulo算法把指令分為Issue,Execute, 和Write Result三步的基礎(chǔ)上,增加一步,稱為Commit(交付,后提交)。

Commit的功能是指令將其結(jié)果交付給(寫入)目的寄存器或存儲(chǔ)單元。必須增加一硬件緩沖存儲(chǔ)器(buffer),供Write Result這一步存放已獲得的結(jié)果,并可以提供給其它指令應(yīng)用這些結(jié)果。當(dāng)指令進(jìn)入Commit這一步時(shí),將結(jié)果從buffer中拷貝到目的寄存器或存儲(chǔ)單元。這一硬件緩沖存儲(chǔ)器稱為重排序緩沖(ROB,Reorder Buffer)。ROB保證指令順序發(fā)射(issue/dispatch),亂序執(zhí)行(execute),順序提交(commit)。通過Reorder buffer(ROB),可以實(shí)現(xiàn)Precise Exception和HW Speculation,同時(shí)由于ROB保證指令順序提交,順便也消除了WAR和WAW 冒險(xiǎn)。Precise Exception(精確異常) 的意思是當(dāng)指令出現(xiàn)異常時(shí)(除0、page fault等),前面的指令已經(jīng)完成,后面的指令不能對(duì)寄存器、內(nèi)存等進(jìn)行修改,即與順序執(zhí)行的效果一樣。

亂序執(zhí)行微架構(gòu)

圖片來源:互聯(lián)網(wǎng)

ROB示意圖,F(xiàn)P指浮點(diǎn)運(yùn)算。 ROB(重排序緩存)的出現(xiàn)還有一個(gè)好處是可以預(yù)測式執(zhí)行,處理器可以根據(jù)預(yù)測執(zhí)行指令,因?yàn)閳?zhí)行完的指令并未提交,而是放在ROB內(nèi),即使出現(xiàn)預(yù)測錯(cuò)誤,執(zhí)行了不該執(zhí)行的指令,但這個(gè)指令不會(huì)提交,會(huì)被直接丟棄。

亂序執(zhí)行,順序提交

圖片來源:互聯(lián)網(wǎng)

這當(dāng)中也有微小區(qū)別,一種稱之為顯式重命名,顯式重命名方案中ROB不記錄指令的結(jié)果,即將提交的數(shù)據(jù)和處于推測狀態(tài)的數(shù)據(jù)都保存在物理寄存器中,因此物理寄存器數(shù)目要高于邏輯寄存器數(shù)目。采用隱式重命名方案時(shí),ROB (Recorder Buffer) 保存正在執(zhí)行、尚未提交的指令的結(jié)果;ARF (ISA Register File) 保存已經(jīng)提交的指令中即將寫入寄存器中的值。隱式重命名方案中ARF只保存已經(jīng)提交的指令的值,處于“推測”狀態(tài)的指令的值由ROB保存,因此需要的物理寄存器數(shù)量與邏輯寄存器數(shù)量相同。隱式重命名方案還需要建立一個(gè)映射表,記錄操作數(shù)在ROB中的位置。

相比于顯式重命名,隱式重命名需要的物理寄存器數(shù)目更少,也就意味著成本低,但每個(gè)操作數(shù)在其生命周期中需要保存在ROB和ARF兩個(gè)位置,讀取數(shù)據(jù)的復(fù)雜度較高、功耗更高。 在英特爾架構(gòu)中,亂序執(zhí)行做得異常復(fù)雜,引入了Allocator定位器,Allocator管理著RAT (RegisterAlias Table,寄存器別名表)、ROB (Re-Order Buffer,重排序緩沖區(qū))和 RRF (RetirementRegister File,退回寄存器文件)。

RAT將重命名的、虛擬的寄存器(稱為Architectural Register 或 Logical Register)指向ROB或者RRF。RAT是一式兩份,每個(gè)線程獨(dú)立,每個(gè)RAT包含了128個(gè)重命名寄存器。RAT指向在ROB里面的最近的執(zhí)行寄存器狀態(tài),或者指向RRF保存的最終的提交狀態(tài)。

ROB將亂序執(zhí)行完畢的指令們按照程序編程的原始順序重新排序的一個(gè)隊(duì)列,以保證所有的指令都能夠邏輯上實(shí)現(xiàn)正確的因果關(guān)系。打亂了次序的指令們(分支預(yù)測、硬件預(yù)取)依次插入這個(gè)隊(duì)列,當(dāng)一條指令通過RAT發(fā)往下一個(gè)階段確實(shí)執(zhí)行的時(shí)候,這條指令(包括寄存器狀態(tài)在內(nèi))將被加入ROB隊(duì)列的一端,執(zhí)行完畢的指令(包括寄存器狀態(tài))將從ROB隊(duì)列的另一端移除(期間這些指令的數(shù)據(jù)可以被一些中間計(jì)算結(jié)果刷新),因?yàn)檎{(diào)度器是In-Order順序的,這個(gè)隊(duì)列(ROB)也就是順序的。從ROB中移出一條指令就意味著指令執(zhí)行完畢了,這個(gè)階段叫做Retire回退,相應(yīng)地ROB往往也叫做Retirement Unit (回退單元,實(shí)際也就是提交單元),并將其劃為流水線的最后一部分。

在一些超標(biāo)量設(shè)計(jì)中,Retire階段會(huì)將ROB的數(shù)據(jù)寫入L1D緩存(這是將MOB集成到ROB的情況),而在另一些設(shè)計(jì)里,寫入L1D緩存由另外的隊(duì)列完成。例如,2008年英特爾推出的Nehalem, 這個(gè)操作就由MOB (Memory Order Buffer,內(nèi)存重排序緩沖區(qū))來完成。

英特爾Nehalem微架構(gòu)前端

圖片來源:互聯(lián)網(wǎng)

Nehalem的128條目的ROB擔(dān)當(dāng)中間計(jì)算結(jié)果的緩沖區(qū),它保存著猜測執(zhí)行的指令及其數(shù)據(jù),猜測執(zhí)行允許預(yù)先執(zhí)行方向未定的分支指令。在大部分情況下,猜測執(zhí)行工作良好——分支猜對(duì)了,因此其在ROB里產(chǎn)生的結(jié)果被標(biāo)識(shí)為已結(jié)束,可以立即被后繼指令使用而不需進(jìn)行L1Data Cache 的Load 操作(這也是ROB的另一個(gè)重要用處,典型的x86應(yīng)用中Load操作是如此頻繁,達(dá)到了幾乎占1/3的地步,因此ROB可以避免大量的Cache Load操作,作用巨大)。在剩下的不幸情況下,分支未能按照如期的情況進(jìn)行,這時(shí)猜測的分支指令段將被清除,相應(yīng)指令們的流水線階段清空,對(duì)應(yīng)的寄存器狀態(tài)也就全都無效了,這種無效的寄存器狀態(tài)不會(huì)也不能出現(xiàn)在RRF里面。

分支預(yù)測

流水線架構(gòu)把指令的執(zhí)行分為了多個(gè)階段,每個(gè)單元只負(fù)責(zé)完成指令執(zhí)行過程中的一個(gè)階段,而中間結(jié)果由專門的流水線寄存器暫存。這樣理論上,一條指令的執(zhí)行假設(shè)被分為5個(gè)階段,那么當(dāng)5個(gè)單元同時(shí)運(yùn)行一段時(shí)間后,理論上相同時(shí)間可以同時(shí)執(zhí)行5條指令,當(dāng)然這只是最簡單的情況,實(shí)際的情況要復(fù)雜得多。

對(duì)于條件跳轉(zhuǎn)指令(匯編層面是JMP等,代碼層面例如if),需要等當(dāng)前的指令執(zhí)行完才知道結(jié)果是true還是false,也就是說,要等待若干個(gè)時(shí)鐘周期后,CPU才可以確定下一條要執(zhí)行的指令究竟是哪個(gè)分支的。

現(xiàn)代CPU都是超過十級(jí)的深流水線,這個(gè)等待時(shí)間太長了,難道這段時(shí)間就只能干等著嗎?當(dāng)然不是,這里CPU就會(huì)采取「分支預(yù)測」的方式,預(yù)測下一條要執(zhí)行的分支指令,并預(yù)先執(zhí)行,如果if執(zhí)行完后發(fā)現(xiàn)和預(yù)測的分支一致,那就中大獎(jiǎng)了,整個(gè)執(zhí)行階段一點(diǎn)都沒有暫停。但如果悲劇地預(yù)測錯(cuò)誤,那么這時(shí)候必須從取址開始,重新執(zhí)行另一個(gè)分支的指令。

分支預(yù)測有兩種,一種是BHT(分支歷史表),一種是BTB(分支目標(biāo)緩存)。BHT已經(jīng)很少人用了,BHT記錄分支指令最近一次或幾次的執(zhí)行情況(成功或不成功),并據(jù)此進(jìn)行預(yù)測;BHT下依然要計(jì)算分支目標(biāo),所以判定分支是否成功所需的時(shí)間應(yīng)該大于確定分支目標(biāo)地址所需的時(shí)間,這時(shí)BHT方法才有用。BHT記錄的是跳轉(zhuǎn)信息,簡單點(diǎn)的,可以用1bit位記錄,例如1表示跳轉(zhuǎn),0表示不跳轉(zhuǎn),而這個(gè)表格的索引是指令PC值;考慮在32位系統(tǒng)中,如果要記錄完整32位的branch history,則需要4Gbit的存儲(chǔ)器,這超出了系統(tǒng)提供的硬件支持能力;所以一般就用指令的后12位作為BHT表格的索引,這樣用4Kbit的一個(gè)表格,就可以記錄branch history了。

BTB將分支成功的分支指令的地址和它的分支目標(biāo)地址都放到一個(gè)緩沖區(qū)中保存起來,緩沖區(qū)以分支指令的地址作為標(biāo)識(shí)。這個(gè)緩沖區(qū)就是分支目標(biāo)緩沖器。BTB用于記錄一條分支指令的跳轉(zhuǎn)地址,由于這兒存儲(chǔ)的是指令地址,例如32位地址,因此,這個(gè)表格就不能做到存儲(chǔ)BHT那樣多的內(nèi)容了,如果也支持4K條指令,則需要128Kbit的存儲(chǔ)空間,這幾乎可以趕上一個(gè)L1Cache的容量了,所以BTB一般很小,就32項(xiàng)或者64項(xiàng)。 

為了盡量提高分支預(yù)測準(zhǔn)確度,BTB又被細(xì)分為NANO、MICRO和主緩存。NANO和MICRO都很小,只有16或32,服務(wù)器級(jí)的有96項(xiàng)。主緩存最高有8K的。數(shù)據(jù)庫以及ERP等應(yīng)用,跳轉(zhuǎn)分支將會(huì)跨過很大的區(qū)域并具有很多的分支。 

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

佐思汽車研究:致力于汽車、TMT、新能源(特別是新能源汽車、智能汽車、車聯(lián)網(wǎng))領(lǐng)域的產(chǎn)業(yè)研究、專項(xiàng)調(diào)研、戰(zhàn)略規(guī)劃和投資咨詢服務(wù)。