暫存器重新命名是為了防止資料衝突嗎

時間 2022-03-24 21:10:11

1樓:匿名使用者

為了避免war和waw帶來的流水線停頓產生氣泡。

詳見tomasulo演算法,指令在發射前分配乙個rs和乙個rob項(這個就是動態暫存器重新命名),執行後的結果會臨時寫在rob中,等到該指令前的所有指令執行完畢,retire時再寫回到arf。

所以你看,結果是臨時寫回rob中,即使多條指令寫回到同乙個暫存器也不受影響,因為不同的指令結果是寫在不同的rob中的。

當然解決raw也有相應的旁路/**技術,也是tomasulo演算法中的一部分。

2樓:匿名使用者

指令序列中,先寫後寫,先讀後寫兩種指令相關形式,雖然存在依賴關係,但是這種依賴關係僅僅是共用同乙個名稱的暫存器而已。它們之間並沒有資料依賴關係。

暫存器重新命名就是修改指令中原來的暫存器,這樣把先寫後寫,先讀後寫兩種指令依賴關係解除掉。指令之間保留下來的只有真正資料依賴關係。

這樣重新命名之後的指令,可以使用另外乙個技術亂序執行。

有資料依賴關係的指令之間,後乙個指令必須等前乙個指令的生成資料後,才能使用該資料繼續執行。

而現在的處理器都採用流水線技術。

如果不使用亂序執行技術,後一條指令依依賴前一條指令的資料,那意味著這個指令流水線並未充分發揮流水線應有的作用。最糟糕的情況處理器還是完整執行一條指令之後,再執行下一條指令。

而使用亂序技術之後,在處理器內部,只要指令所依賴的資料準備後了,就立即送入指令流水線執行。而那些未準備好資料的指令,在乙個臨時指令池裡儲存。而指令在流水線內處理完畢生成資料時,會將資料反饋給前段的指令池,那些依賴該資料的指令又可以送入流水線內。

暫存器重新命名的指令在流水線內執行完畢之後,會根據情況將資料重新回寫到原來的暫存器裡。

相當於重新命名的暫存器最後將結果值又恢復到原來暫存器名稱。

cpu內部暫存器組結構及其功能是什麼?

3樓:匿名使用者

1.什麼是暫存器 所謂暫存器(register),它是cpu內部用來存放資料的一些小型儲存區域,用來暫時存放參與運算的資料和運算結果。其實暫存器就是一種常用的時序邏輯電路,但這種時序邏輯電路只包含儲存電路。

暫存器的儲存電路是由鎖存器或觸發器構成的,因為乙個鎖存器或觸發器能儲存1位二進位制數,所以由n個鎖存器或觸發器可以構成n位暫存器。 2.暫存器與cpu指令 在講cpu的暫存器之前,我們先了解一下cpu指令系統。

指令系統指的是乙個cpu所能夠處理的全部指令的集合,athlon xp和p4都是基於x86指令集,這是cpu的根本屬性,決定cpu執行什麼樣的程式。 指令一般分為:算術邏輯運算指令、浮點運算指令、位操作指令及其他的一些非運算指令,其中整數、位址、指令指標和浮點資料是按照資料形式來劃分的。

通常我們把需要cpu進行不同處理的單個資料稱為標量資料(scala data)。標量資料既可以是整數資料,也可以是浮點資料。其中整數標量資料的存放區一般為通用暫存器(gpr),浮點標量資料的存放區一般為浮點暫存器(fpr)。

與標量資料相對的是向量資料(vector data),所謂向量資料就是指一列需要由處理器作相同處理的資料集合。比如處理器在做***編碼的過程中,需要對記憶體中的音訊檔案裡的各位元組資料作相同的***編碼操作。那麼通常使用mmx或sse這類單指令多資料流(simd)指令,將數個位元組打包為一組向量資料,存放在mmx或sse暫存器中,再送往相應的功能單元進行統一操作。

其中通用暫存器是處理器中最快的儲存器,用來儲存參加運算的運算元和中間結果。在通用暫存器的設計上,risc與cisc(也就是我們常說的x86架構)有著很大的不同。cisc的暫存器通常很少——只有8個通用暫存器。

由於cpu在執行指令過程中,存在指令依賴性,在一定程度上使得x86 cpu不能在每個時鐘週期中立即發布大量的指令。所謂「依賴性」就是指令的執行需要前個指令的運算結果。比如程式設計師經常使用的分支程式,請看下面這個例子:

a=c*1 b=a+2 只要變數a的值還不知道,b=a+2就不能進行運算。也就是說,只要指令1的結果沒有寫進暫存器,cpu排程器就不能把指令2發布到執行單元。由於程式分支會造成具有較長流水線cpu執行停滯的,目前常用的解決方法是採用分支**。

不過,分支**同樣存在乙個問題:流水線越長,指令潛伏期也越長,等待前一指令運算結果的時間也越長,同樣會造成cpu執行停滯。我們知道,程式指令通常都有各型別的條件分支語句,通過驗證條件決定執行路線。

但cpu執行單元內是通過一項特殊的**機制選擇一條路線直接執行(這樣可以避免驗證語句條件而處於等待情況),然後在後面進行驗證。如果**正確則繼續往下執行,如果發現以前的**錯誤,那麼就必須返回原地重新開始,以前的指令就會作廢。 因此,管線越長,意味著出現分支**錯誤的機會就越多,越多在管線內的指令會被清除掉,而且重新讓管道填滿指令的時間也會越長。

對於普通處理器來說,如果出現分支**錯誤,cpu就不得不將整條流水線清空後從錯誤的地方重新裝滿資料、重新執行。毫無疑問這將花更多的時間,整體效能就會下降。因此,針對通用暫存器少的問題,在x86架構中比較完美的解決方法就是增加暫存器的數量和採用「亂序執行」。

3.為什麼暫存器不夠用 在上面我們已經提到,暫存器只是用來暫時存放指令值的,如果cpu需要把兩個值加起來,它需要用1個暫存器來存放運算結果,用2個暫存器來存放相加的數值。例如,在以下的方程式中:

a = 2 + 4 * 在暫存器1儲存「2」; * 在暫存器2儲存「4」; * 在暫存器3儲存「暫存器1 + 暫存器 2」; 因為在微處理器裡面有超過3個暫存器,因此這個運算能夠輕易地執行,不會造成用光暫存器的情況。在這些運算被執行之後,所有的3個數值都能夠被保留並重新使用,因此如果我們再想在結果加上2的話,處理器只需要執行:暫存器 1 + 暫存器 3 就可以了。

如果微處理器僅有2個剩餘的暫存器,而我們又需要再次使用2和4的值,那麼這些值在覆蓋結果a之前,必須儲存在主記憶體之中 。運算執行的過程則會變成如下所示: * 在暫存器1儲存 「2」; * 在暫存器2儲存「4」; * 在主記憶體的某個空間儲存「暫存器1 + 暫存器2」; 我們可以看到這裡使用了其它的記憶體訪問過程,而在這期間其實還有我們沒有提到的其它處理過程,比如主記憶體的定位也需要佔據暫存器,以便讓cpu 告訴裝載/儲存單元該往**傳送資料 。

如果我們需要使用到這些結果的話,那麼cpu將不得不首先到主記憶體中找回這些結果,把目前滿載的暫存器驅逐一些資料,把它們寫入主記憶體,然後再把尋找到的資料儲存在暫存器裡。 這裡大家應該能夠明白吧,對記憶體的訪問次數將會可怕地增加;你需要訪問記憶體的時間越多,那麼處理器等待工作完成的時間就越長——因而造成效能的下降。因此面對超標量cpu在並行處理大量運算,x86體系僅有的8個通用暫存器遠遠不能滿足需要,在同一時鐘週期中,如果有3個指令發布,你就需要3個輸出暫存器和6個輸入暫存器。

我們該怎麼辦呢?聰明的工程師們發現了突破這個限制的方法:「暫存器重新命名」。

4.暫存器重新命名技術 暫存器重新命名,是cpu在解碼過程中對暫存器進行重新命名,解碼器把「其它」的暫存器名字變為「通用」的暫存器名字,本質上是通過乙個**把x86暫存器重新對映到其它暫存器,這樣可以讓實際使用到的暫存器遠大於8個。這樣做的好處除了便於前面指令發生意外或分支**出錯時取消外,還避免了由於兩條指令寫同乙個暫存器時的等待。

下面我們以乙個超標量cpu執行8個算術指令為例:假設它在每個時鐘週期中能對2個指令解碼,引出計算結果是在指令發布後3個時鐘週期發生的: (1)在第1個時鐘週期,兩個指令發布:

它們互不關聯,因此,它們將在3個時鐘週期後(第4個時鐘週期)引出; (2)在第2個時鐘週期,我們首次遇到了「指令依賴」,指令3需要指令2的結果,此時指令3不能開始發布; (3)如果是按序執行,指令4、5、6就不能在指令3前發布。只有在第5個時鐘週期時(指令2的結果已得到)才能發布指令3; (4)在第6個時鐘週期有個大問題:我們想把結果寫到暫存器r1,但這將改變指令5的結果。

因此,我們只有在r1空閒時(第10個時鐘週期)才能發布指令6。 按照正常情況處理的話,儘管這個cpu每個時鐘週期可以對2個指令解碼,但它每個時鐘週期的指令執行數只有0.53。

如果每次程式所需的暫存器正被使用,我們可以把資料放到其它的暫存器中,在第6個時鐘週期將暫存器r1重新命名,指令6和指令8不再耽誤cpu的工作。結果是我們能夠將每個時鐘週期的指令執行數提高50%。暫存器重新命名技術可以使x86 cpu的暫存器可以突破8個的限制,達到32個甚至更多。

暫存器重新命名技術現在已經深深地扎根於超標量cpu中了。5.亂序執行技術 除此之外,處理器工程師還引入了亂序執行技術,從一定程度上來緩解通用暫存器不足的問題。

採用亂序執行技術的目的是為了使cpu內部電路滿負荷運轉並相應提高了cpu執行程式的速度。 這好比請a、b、c三個名人為春節聯歡晚會題寫橫幅「春節聯歡晚會」六個大字,每人各寫兩個字,如果這時在一張大紙上按順序由a寫好「春節」後再交給b寫「聯歡」,然後再由c寫「晚會」,那麼這樣在a寫的時候,b和c必須等待,而在b寫的時候c仍然要等待而a已經沒事了。但如果採用三個人分別用三張紙同時寫的做法,那麼b和c都不必等待就可以同時各寫各的了,甚至c和b還可以比a先寫好也沒關係(就像亂序執行),但當他們都寫完後就必須重新在橫幅上按「春節聯歡晚會」的順序排好(自然可以由別人做,就象cpu中亂序執行後的重新排列單元)才能掛出去。

不過,雖然採用暫存器重新命名技術、亂序執行技術,但仍不能從根本上解決x86處理器通用暫存器不足的問題。以暫存器重新命名技術來說,這種技術的暫存器操作相對於risc來說,要花費乙個時鐘週期來對暫存器進行重新命名,這無形中降低了處理器效能以及流水線工作效率,也增加了程式和編譯器的優化難度。針對這個問題,最新的x86-64架構中(k8處理器),amd在x86架構基礎上將通用暫存器和simd暫存器的數量增加了1倍:

其中新增了8個通用暫存器以及8個simd暫存器作為原有x86處理器暫存器的擴充。 這些通用暫存器都工作在64位模式下,經過64位編碼的程式就可以使用到它們。這些64位暫存器稱為rax、rbx、rcx、rdx、rdi、rsi、rbp、rsp、rip以及eflags,在32位環境下並不完全使用到這些暫存器,同時amd也將原有的eax等暫存器擴充套件至64位的rax,這樣可以增強通用暫存器對位元組的操作能力。

從擴充方式上看,eax等暫存器可以看做是rax的乙個子集,系統仍然可以完整地執行以往的32位編碼程式。增加通用暫存器除了可高效儲存資料外,還可作為定址時的位址指標,從而縮短指令長度和指令執行時間,加快cpu的運算處理速度,同時也給程式設計帶來方便。 此外,為了保證k8的分支**更有效率,k8的分支**暫存器增加到64個。

分支指令可以被設為真或假,而每個指令中的6位被分配到單獨乙個**暫存器中,只有**暫存器被設定為「真」時,那些指向**暫存器為「真」的指令結果才會被執行。其次由於所有的分支都能並行執行,cpu所花的時間同隻執行單個分支的時間是相同的,降低了**出錯的風險。第三由於cpu不再跳躍執行,它不會把程式**分成小塊。

也就是說,稍前和稍後的程式**可以打包。這樣cpu能夠一併將它們發布,增大並行工作量。從而使效能提高10%~15%,特別是在整數**部分。

不過在x86-64中,暫存器的擴充套件部分似乎僅對於整數、位址資料有效。對浮點和向量資料則仍然保持原樣。我們能從k8向64位的擴充套件所獲得的好處,只不過是可以在同樣一條指令中,處理更大數值的整數數值以及管理空間更大的記憶體區域而已。

而在32位的情況下,由於通用暫存器只能容納最大32位的資料,因此顯然要花費更多條指令對尺寸超過32位的資料進行處理。這種改進對伺服器、科學計算這樣的領域具有一定的意義,但顯然並不是普通家用環境急需的改進。 可以說,處理器的暫存器對處理器的效能有著巨大的影響。

但是無論怎麼發展,通用型cpu目前還沒有脫離x86架構的限制,也許有一天,新的暫存器技術能讓我們的cpu變得更加功能強大!

c語言中的自動變數和暫存器變數是什莫

手機使用者 c語言學習之變數儲存 c語言中對變數的說明包括兩方面的內容 變數型別以及變數的儲存型別。變數型別如 int 整形 char 字元型 是用來說明變數所佔用的記憶體空間的大小。變數儲存型別用來說明變數的作用範圍。c語言的變數儲存類有 自動類 暫存器類 靜態類和外部類。關鍵字auto加在變數名...

計算機顯示 網路上有重新命名 是怎麼回事情,怎麼解決

第一代菜鳥 在ip那改了名就行了 汗鳴 對,ip衝突。我學校裡的機子經常這樣。 這種問題通常只會出現在區域網內,在同乙個區域網裡面,每台電腦除了有唯一的內部ip位址外,還有自己的網路標識,說直接點就是自己的名字,如果有人電腦的名稱和你的一樣,就會出現網路重名現象。解決的辦法就是更改網路標識,只要你的...