版權(quán)歸原作者所有,如有侵權(quán),請聯(lián)系我們

[科普中國]-寄存器重命名

科學(xué)百科
原創(chuàng)
科學(xué)百科為用戶提供權(quán)威科普內(nèi)容,打造知識科普陣地
收藏

寄存器重命名是計算機(jī)CPU的微體系結(jié)構(gòu)(Microarchitecture)中的一種技術(shù),避免了機(jī)器指令或者微操作不必要的順序化執(zhí)行,從而提高了處理器的指令級并行的能力。

問題定義計算機(jī)的CPU往往用寄存器來保存指令的操作數(shù)與結(jié)果。x86指令集體系結(jié)構(gòu)有8個整數(shù)寄存器,x86-64指令級體系結(jié)構(gòu)有16個整數(shù)寄存器,許多RISC體系結(jié)構(gòu)有32個整數(shù)寄存器,IA-64有128個整數(shù)寄存器. 在小型處理器,這些指令集體系結(jié)構(gòu)寄存器直接對應(yīng)于寄存器堆中的物理寄存器。

不同的指令可以有不同的執(zhí)行時間,特別是CISC指令集體系結(jié)構(gòu)上更為明顯。例如,一條讀內(nèi)存的指令的執(zhí)行時間,足夠執(zhí)行幾百條其它指令。因此,在允許多條指令并行執(zhí)行的情況下,那些指令地址順序靠后的指令,比讀取內(nèi)存指令更早完成,這就形成了指令執(zhí)行順序不同于其在程序中的順序。這種亂序執(zhí)行是高性能CPU提高運(yùn)算速度的關(guān)鍵辦法之一。

考慮下述代碼片段在亂序執(zhí)行CPU上的運(yùn)行:

|| ||

第4、第5、第6條指令在功能上是不依賴于第1、第2、第3條指令的。但是處理器卻不能在第3條指令完成前去完成第4條指令(在指令流水線上,不能在第3條指令完成前,就提交第4條指令的結(jié)果),因?yàn)檫@可能會導(dǎo)致第3條指令把錯誤的數(shù)據(jù)寫入內(nèi)存。

通過改變一些寄存器的名字,可以使上例中指令并行執(zhí)行所受的限制:

|| ||

現(xiàn)在,4、5、6號指令可以與1、2、3號指令并行執(zhí)行,二者沒有依賴問題。這使得程序可以用更短時間完成。

編譯器會盡力檢測出類似這樣的問題,并把不同的寄存器分配給不同的指令使用。但是,受指令集體系結(jié)構(gòu)的限制,匯編程序可以使用的寄存器名字的數(shù)量是有限的。很多高性能CPU的實(shí)現(xiàn)—微體系結(jié)構(gòu)—有很多物理寄存器,可以在處理器指令流水線執(zhí)行時把這些指令集體系結(jié)構(gòu)寄存器映射為不同的物理寄存器,從而在硬件級提供了額外的并行能力。

數(shù)據(jù)沖突主條目:數(shù)據(jù)沖突

如果多條指令使用了同一個存儲位置,這些指令如果不按程序地址順序執(zhí)行可能會導(dǎo)致3種數(shù)據(jù)沖突(data hazard):

先寫后讀(Read-after-write,RAW):從寄存器或者內(nèi)存中讀取的數(shù)據(jù),必然是之前的指令存入此處的。直接數(shù)據(jù)相關(guān)(true data dependency)

先寫后寫(Write-after-write,WAW):連續(xù)寫入特定的寄存器或內(nèi)存,那么該存儲位置最終只包含第二次寫的數(shù)據(jù)。這可以取消或者廢除第一次寫入操作。WAW相關(guān)也被說成是“輸出相關(guān)”(output dependencies)。

先讀后寫(Write-after-read,WAR):讀操作獲得的數(shù)據(jù)是此前寫入的,而不是此后寫操作的結(jié)果。因此并行和亂序時無法改善的資源沖突(antidependency)。WAW和WAR可以通過寄存器重命名解決(register renaming),不必等待所有讀操作完成后再執(zhí)行寫操作,可以保持這個存儲位置的兩份副本:老值與新值。讀老值的操作可以繼續(xù)進(jìn)行,無需考慮那些寫新值甚至寫新值之后的讀新值的操作。產(chǎn)生了額外的亂序執(zhí)行機(jī)會。當(dāng)所有讀老值操作被滿足后,老值所使用的寄存器既可以釋放。這是寄存器重命名的實(shí)質(zhì)。

任何被讀或?qū)懙拇鎯Χ际强梢员恢孛?。最??紤]的是通用整數(shù)寄存器與浮點(diǎn)寄存器。標(biāo)志寄存器、狀態(tài)寄存器甚至單個狀態(tài)位也是常見的重命名的對象。

內(nèi)存位置也可以被重命名,雖然這么做不太常見。全美達(dá)的Crusoe處理器的gated store buffer是一種內(nèi)存重命名。

如果程序沒有立即重用寄存器,它就不需要寄存器重命名這種機(jī)制。例如IA-64指令集體系結(jié)構(gòu)提供了128個通用寄存器,就是出于此考慮。但這種努力也遇到了困難:

編譯器很難完全避免在不導(dǎo)致程序尺寸大增的同時避免重用寄存器。程序的循環(huán)的連續(xù)迭代執(zhí)行就需要復(fù)制循環(huán)體的代碼以使用不同的寄存器,這種技術(shù)叫做循環(huán)展開。

大量的寄存器,需要在指令的操作數(shù)中用很多位去指出,導(dǎo)致程序尺寸變大。

很多指令集在歷史上就使用了很少的寄存器,出于兼容原因現(xiàn)在也很難改變。

程序的代碼尺寸增加,會導(dǎo)致指令高速緩存的未命中(cache miss)增加,處理器執(zhí)行停頓等待從低級存儲中讀入代碼。這對運(yùn)算性能的影響是致命的。

體系結(jié)構(gòu)寄存器與物理寄存器編譯器或者匯編器生成的機(jī)器語言程序讀寫有限數(shù)量的指令集體系結(jié)構(gòu)(ISA)寄存器。例如,Alpha ISA使用32個64位寬整數(shù)寄存器,32個64位寬浮點(diǎn)寄存器。這些體系結(jié)構(gòu)寄存器,是程序可以直接訪問的邏輯上的寄存器。如果程序員在調(diào)試器中把這個程序暫停,可以觀察到這64個寄存器與一些狀態(tài)寄存器當(dāng)前存儲的值。

一款特定的處理器,實(shí)現(xiàn)了這種處理器體系結(jié)構(gòu)。例如Alpha 21264有80個整數(shù)寄存器、72個浮點(diǎn)寄存器,作為處理器內(nèi)物理實(shí)現(xiàn)的寄存器。也就是說,Alpha 21264處理器有80個物理存在的位置存儲整數(shù)運(yùn)算的結(jié)果,72個位置存放浮點(diǎn)運(yùn)算的結(jié)果。實(shí)際上,該款處理器有更多的物理存在的存儲位置,但與寄存器重名關(guān)系不大。

下面介紹兩種寄存器重命名方法,區(qū)別于為執(zhí)行單元準(zhǔn)備數(shù)據(jù)的電路。處理器把指令流使用的體系結(jié)構(gòu)寄存器改為用若干位表示的tags所索引的物理寄存器。

tag索引的寄存器堆(tag-indexed register file)是一個很大的寄存器堆,當(dāng)一條指令發(fā)射(issue)給執(zhí)行單元,源操作數(shù)的寄存器tags將發(fā)送給物理寄存器堆,其中該tags所對應(yīng)的物理寄存器的內(nèi)容被發(fā)送給該執(zhí)行單元。

保留站(reservation station)方法,存在多個小型相關(guān)的寄存器堆,通常是每個執(zhí)行單元的輸入口都有一個物理寄存器堆。發(fā)射隊(duì)列中的每條指令的每個操作數(shù)對應(yīng)著這個物理寄存器堆的一個存儲位置。當(dāng)一條指令發(fā)射給某個執(zhí)行單元,執(zhí)行單元對應(yīng)的寄存器堆的相應(yīng)條目被讀出發(fā)送給執(zhí)行單元。

體系結(jié)構(gòu)寄存器堆(Architectural Register File)或者引退寄存器堆(Retirement Register File,RRF):存儲了被提交的體系寄存器的狀態(tài)。通過邏輯寄存器的號來查詢這個寄存器堆。重排序緩沖區(qū)(reorder buffer)中的引退(retired)或者說提交(committed)指令,把結(jié)果寫入這個寄存器堆。

遠(yuǎn)期寄存器堆(Future File):處理器對分支做投機(jī)執(zhí)行的寄存器的狀態(tài)保存于此。使用邏輯寄存器號來索引訪問。在Intel P6微體系結(jié)構(gòu),稱之為Active Register File。

歷史緩沖區(qū)(History Buffer):用于保存分支時的邏輯寄存器狀態(tài)。如果分支預(yù)測失敗,將使用歷史緩沖區(qū)的數(shù)據(jù)來恢復(fù)執(zhí)行狀態(tài)。

重排緩沖區(qū)(Reorder Buffer,ROB):為了實(shí)現(xiàn)指令的順序提交,處理器內(nèi)部使用了一個Buffer。如果在該緩沖區(qū)中排在一條指令之前的所有都已經(jīng)提交,沒有處于未提交狀態(tài)的(稱作in flight),則該指令也被提交(即確認(rèn)執(zhí)行完畢)。因此重排緩沖區(qū)是在遠(yuǎn)期寄存器堆之后,體系結(jié)構(gòu)寄存器堆之前。提交的指令的結(jié)果寫入體系寄存器堆。

重排緩沖區(qū)分為data-less與data-ful兩種。

Willamette's ROB,其條目指向物理寄存器堆(PRF)中的寄存器。此外還包括一些簙記數(shù)據(jù)。這是第一種亂序執(zhí)行設(shè)計,由Andy Glew在Illinois用HaRRM完成。

Intel P6的ROB,條目包含了數(shù)據(jù)。沒有單獨(dú)的物理寄存器堆。來自ROB的數(shù)據(jù)在指令提交后將復(fù)制到引退寄存器堆(RRF)。

細(xì)節(jié):tag索引寄存器堆這種重命名模式用于MIPS R10000、Alpha 21264,以及AMD Athlon的浮點(diǎn)部分。

在重命名階段,每個被引用的體系結(jié)構(gòu)寄存器(不論是讀還是寫)按其體系結(jié)構(gòu)索引號到重命名文件(remap file)中查找,取出一個tag與一個ready位。如果一個排隊(duì)在前的寫操作要把數(shù)據(jù)寫入該寄存器,但該寫操作尚未執(zhí)行完,則這個tag是未就緒的(non-ready)。

對于寄存器讀,這個tag替換了體系結(jié)構(gòu)寄存器,即這種先寫后讀的寄存器數(shù)據(jù)相關(guān)必須恪守,該讀操作只有在該ready位是就緒之后才可以被分派執(zhí)行。

對于寄存器寫,從一個空閑tag先進(jìn)先出隊(duì)列(free tag FIFO)取出一個新的tag,且這項(xiàng)新的映射條目寫入重命名文件,未來的讀取該體系結(jié)構(gòu)寄存器的指令將指向這個新的tag,即“寫后寫”是一種寄存器數(shù)據(jù)偽相關(guān),用這種重命名就可去去掉偽相關(guān)。這個tag被標(biāo)記為未就緒,因?yàn)閷懖僮魃形磮?zhí)行。以前為該體系結(jié)構(gòu)寄存器分配的物理寄存器被保存在指令的重排緩沖區(qū)(reorder buffer)中;即:以前為該體系結(jié)構(gòu)寄存器分配的物理寄存器可以從重排緩沖區(qū)中查到。重排緩沖區(qū)是一個先進(jìn)先出隊(duì)列,依照指令解碼的順序(即指令在程序中的先后順序)安排指令引退的順序。

操作數(shù)寄存器被重命名后的指令將被放入不同的發(fā)射隊(duì)列(issue queues)。這些指令等待所需的各種資源(如源操作數(shù)對應(yīng)的物理寄存器)就緒。

當(dāng)指令執(zhí)行完,其結(jié)果的tags將被公告,發(fā)射隊(duì)列中用這些公告的tags匹配那些未就緒的tags。一個匹配就意味著該操作數(shù)就緒了。重命名文件也去匹配這些公告的tags,從而標(biāo)記哪些對應(yīng)的物理寄存器是就緒的。

當(dāng)發(fā)射隊(duì)列中的某條指令的所有操作數(shù)是就緒的,這條指令就是發(fā)射就緒。在每個周期,發(fā)射隊(duì)列撿出一些就緒指令,發(fā)送到功能單元。未就緒指令仍然留在發(fā)射隊(duì)列中。這種從發(fā)射隊(duì)列中無序刪除指令,使得發(fā)射隊(duì)列的電路實(shí)現(xiàn)占用面積大、功耗高。

被發(fā)射的指令讀取源操作數(shù)的tag索引在物理寄存器堆中對應(yīng)的物理寄存器(忽略掉剛剛公告過的操作數(shù)),然后開始執(zhí)行指令。

指令執(zhí)行結(jié)果寫入目的操作數(shù)的tag索引在物理寄存器堆對應(yīng)的物理寄存器,同時公告給每個功能單元輸入端的旁路網(wǎng)絡(luò)(bypass network,即把執(zhí)行結(jié)果“直通”給流水線各個步驟的中間緩沖)。

寫寄存器的指令在引退時,把被寫的目的操作數(shù)寄存器使用過的上一個tag放入“空閑tag隊(duì)列”中,使得它可以被其它被解碼的指令重用。而該指令的目的操作數(shù)寄存器當(dāng)前對應(yīng)的tag仍然被占用,因?yàn)楹竺婵赡苓€有指令需要讀取當(dāng)前tag對應(yīng)的物理寄存器的內(nèi)容。

一個異常(將導(dǎo)致中斷)或者分支預(yù)測失敗導(dǎo)致了重命名文件退回到最后一條有效的指令的重命名狀態(tài),通過組合狀態(tài)的快照(在歷史緩沖區(qū))與重排緩沖區(qū)中等待順序引退的指令的以前用過的tags。這種機(jī)制可以實(shí)現(xiàn)恢復(fù)任意時刻的重命名狀態(tài)。

細(xì)節(jié):保留站主條目:保留站

這種重命名模式用于AMD K7與K8的整數(shù)寄存器設(shè)計。

在重命名階段,作為源操作數(shù)的體系結(jié)構(gòu)寄存器在遠(yuǎn)期寄存器堆與重命名文件中查找對應(yīng)的物理寄存器。如果沒有寫指令還沒有完成寫入該物理寄存器,則說明這個源操作數(shù)已經(jīng)就緒。當(dāng)這條指令被放入發(fā)射隊(duì)列,從遠(yuǎn)期寄存器堆相應(yīng)的物理寄存器讀出內(nèi)容放入保留站中對應(yīng)的條目。指令對目的寄存器的寫入,在重命名文件中的產(chǎn)生了一個新的、未就緒的tag。tag數(shù)通常是按照指令的順序分配,因此不需要空閑tag先進(jìn)先出隊(duì)列。

如同tag索引模式,發(fā)射隊(duì)列中的未就緒操作數(shù)等待匹配的tag公告。但不同于tag索引模式,tag的匹配導(dǎo)致對應(yīng)的內(nèi)容數(shù)據(jù)寫入發(fā)射隊(duì)列對應(yīng)的保留站的條目。

被發(fā)射的指令從保留站讀取它的操作數(shù),忽略掉那些剛剛公告過的操作數(shù),然后開始執(zhí)行。保留站寄存器堆通常很小,可能只有8個條目。

指令執(zhí)行結(jié)果寫入重排緩沖區(qū),以及保留站(如果發(fā)射隊(duì)列有匹配的tags),以及遠(yuǎn)期寄存器堆。

指令引退時,復(fù)制重排序緩沖區(qū)中的值到體系結(jié)構(gòu)寄存器堆。體系結(jié)構(gòu)寄存器堆用于從異?;蛘叻种ьA(yù)測失敗時恢復(fù)。

在指令引退時可以識別出異常與分支預(yù)測失敗,引起體系結(jié)構(gòu)寄存器堆覆蓋掉遠(yuǎn)期寄存器堆的內(nèi)容,并標(biāo)記重命名文件中所有寄存器都是就緒。通常,沒有辦法為一條處于解碼與引退之間的指令恢復(fù)遠(yuǎn)期寄存器堆,因此通常沒有辦法在更早期為分支預(yù)測失敗做恢復(fù)工作。

比較兩種模式在兩種模式下,指令被順序送入發(fā)射隊(duì)列,但從發(fā)射隊(duì)列移出是亂序的1。

保留站具有更好的延遲(latency)性能。因?yàn)橹孛A段直接獲得寄存器內(nèi)容,而不是獲得物理寄存器號,再用這個號去獲得內(nèi)容值。

保留站具有更好的從指令發(fā)射到執(zhí)行的延遲性能。因?yàn)槊總€本地寄存器堆遠(yuǎn)小于那種大型的用tag索引的中央寄存器堆。tag產(chǎn)生與異常處理也更為簡單。

與tag索引的簡單的寄存器堆相比,保留站的物理寄存器堆的總規(guī)模更大,功耗更大,更為復(fù)雜。更糟糕的是,每個保留站的每個條目可以被每條結(jié)果總線寫入。例如,每個功能單元具有8條發(fā)射隊(duì)列條目的處理器,相比于tag索引的模式有9倍的旁路網(wǎng)絡(luò),結(jié)果直通(forwarding)需要更大的功耗與面積。

保留站模式在4個位置(遠(yuǎn)期寄存器堆,保留站,重排序區(qū)、系統(tǒng)結(jié)構(gòu)寄存器堆)保存結(jié)果值。而tag索引模式只需要在物理寄存器堆保存結(jié)果值。由于結(jié)果值來自功能單元,保留站模式必須公告結(jié)果到許多存儲位置,用掉了非常多的功耗、面積、時間。如果處理器具有非常精確的分支預(yù)測、非常關(guān)注執(zhí)行延遲,保留站也是個很好的選擇。

歷史IBM System 360 Model 91是早期支持亂序執(zhí)行的計算機(jī)。它使用Tomasulo算法用到了寄存器重命名。

1990,POWER1是第一種使用了寄存器重命名與亂序執(zhí)行的微處理。

最初的R10000設(shè)計既沒有發(fā)射隊(duì)列壓偏(collapsing),也沒有可變優(yōu)先權(quán)編碼,因此遇到了寄存器資源餓死(starvation)—最老的指令在隊(duì)列中一直沒有被發(fā)射,直到解碼指令因?yàn)槿狈芍孛奈锢砑拇嫫鞫耆nD,而所有就緒指令都已經(jīng)發(fā)射了。后來修改設(shè)計的R12000使用了部分可變優(yōu)先級編碼來克服此問題。

早期亂序執(zhí)行處理器并不區(qū)分重命名與重排序緩沖區(qū)/物理寄存器堆的功能。因此,某些最早期的產(chǎn)品,如Sohi的RUU,Metaflow DCAF,組合了調(diào)度、重命名,存儲在一個結(jié)構(gòu)中。

大多數(shù)現(xiàn)代處理器的重命名使用了一個映射表,用邏輯寄存器號去索引。例如Intel P6微體系結(jié)構(gòu)。遠(yuǎn)期寄存器堆也是如此,并在此存放數(shù)據(jù)。

但是,更早的處理器使用內(nèi)容尋址存儲技術(shù)實(shí)現(xiàn)重命名,例如HPSM RAT,以及存儲器別名表(Register Alias Table)。

某種程度上,亂序執(zhí)行的微體系結(jié)構(gòu)的故事就是這些內(nèi)容尋址存儲如何逐步被清除。

Intel P6微體系結(jié)構(gòu)是Intel處理器中第一種亂序執(zhí)行、寄存器重命名。P6發(fā)展出了Pentium Pro、Pentium II、Pentium III、Pentium M、Core、Core 2等處理器系列。

本詞條內(nèi)容貢獻(xiàn)者為:

曹慧慧 - 副教授 - 中國礦業(yè)大學(xué)