CPU設計原理是什么
你知道cpu的設計原理嗎?下面將由學習啦小編帶大家來解答這個疑問吧,希望對大家有所收獲!
1.1 指令的執(zhí)行過程(這里沒有涉及到高級語言的編譯,所以沒有翻譯指令)
CPU的性能由哪些因素決定?我想大多數人都會知道時鐘周期這個概念,而另兩條“指令數目”,“指令所需時鐘周期數(CPI)”是并不為人所知的。而不同
的內部架構,也便深刻的影響了CPI的大小,所以有些處理器頻率低但是處理任務更快。不過別急,一口吃一個胖子是不行的,在我們對CPU的架構進行探討之
前,先來看看CPU是怎么處理一條指令的。
一條指令,首先會根據程序計數器(記錄當前運行的指令地址,本身也是一種寄存器)從內存中去處指令,通過指令字段的內容,選擇讀取一個或者兩個寄存器(在
匯編語言中,一條代碼,即一個指令只能使用1或2個寄存器進行加減乘除運算,而寄存器,就是記錄數據的一個東西,當然他還有更多用途,之后我們會提及)一
旦取得寄存器的操作數后,就可以對指令進行定性,大致分為三種,存儲訪問,算術邏輯和分支(分支也可以叫做跳轉,一般的高級語言都用if語句,判斷一些特
定條件從而進行兩種或者更多的操作)存儲訪問指令需要對存儲單元進行讀出或者寫入而訪問寄存器;算術邏輯指令需要將ALU(運算器)計算得到的數據寫回寄
存器;而分支指令則會通過對數據的比較,決定是否對下條指令地址進行修改(也就是是否進行if語句中的or后面的語句)
話外音:一條高級語言首先會被編譯為匯編語言,之后通過指令集將其編譯為二進制信號,從而讓CPU明白它需要做哪些操作。
不要將緩存和寄存器的概念混淆,最好從百度百科上看看相應資料。緩存我們會在第三大章進行詳細討論。
1.2 數據通路的建立
什么叫數據通路?我想聰明的你一定知道,讓一條指令順暢執(zhí)行下去,這就是一條數據通路,它包括指令,數據存儲器,寄存器堆,運算單元和加法器(加法器是對
程序計數器進行調節(jié)的,也就是說當前指令執(zhí)行完畢之后,加法器對程序計數器加上4,就可以切換到下一個指令地址,關于為什么加4這里不多說,在第三大章我
們會提及)。
想要構成數據通路,首先需要一個存儲程序指令的地方,那么我們就需要一個存儲單元來存儲程序指令,并根據所給地址提供指令。當前需要執(zhí)行的指令一定要放在一個存儲單元中,這就是我們之前提到的程序計數器(PC),然后同一個加法器增加PC的值使它指向下一條指令的地址。
得到了指令地址,就可以讓ALU對指令進行處理,從而得到結果,而ALU想要進行計算,就需要從寄存器獲得數據并寫入寄存器,這樣,我們就需要一個寄存器堆,來暫時存儲這些指令地址,信息等等。
如果是儲存訪問指令和算術指令的話,那么接下來只需要將寄存器的數據顯示,或者暫時儲存就可以了,若是分支指令,就需要對ALU的數據和寄存器的數據進行
比較,如果為真,則執(zhí)行if語句后緊跟的語句,如果為假,就會執(zhí)行if語句中or后緊跟的語句,所以說分支指令總是延遲的,因為在沒有得出指令的真假時我
們不能對接下來的指令進行處理。
1.3 指令的處理實現
一條指令,通過拆分(解碼器就是對指令進行拆分,重排等操作的,使用邏輯電路從而達到了一種特殊算法),因為ALU的處理能力是一定的,所以有些復雜指令不能在一個周期內處理完,而需要拆分或者讓ALU利用更長的一個周期重復處理這段指令。
對于單周期實現,和1.2節(jié)中的數據通路非常相近,如果有不熟悉的朋友可以回閱上一節(jié)。
多周期的數據通路,與單周期通路最本質的區(qū)別有三點:
1 指令和數據使用相同的儲存單元
2 只有一個ALU(也可以使多個,但目前不對其進行討論),沒有了加法器
3 每個重要的功能單元都加上了一些寄存器存儲輸出值,使后面的時鐘周期得到需要的信息(這是寄存器的另一個用處)。
當一個時鐘周期結束后,我們只需要將處理得到的結果反饋給PC程序計數器,那么它就可以再次發(fā)射指令,所以就沒有必要安置加法器。
說了這么多,相信有心的朋友們就會發(fā)現,其實我們所說的單周期指令實現,就是早期的CISC復雜指令集計算機,而多周期就是RISC精簡指令集計算機。而
CISC這個東東有兩個致命缺點,第一,它不能夠很好的進行流水操作(第二大章的內容,以后詳細講解),第二,因為指令的復雜程度不一,那么如果為了性能
而使用可變時鐘周期的設計,會大大增加控制器等其他單元的設計問題,而若是使用固定的時鐘頻率,又會造成極大的浪費,所以CISC現在已經基本被拋棄了。
10月1日
1.4 異常
在CPU設計中,最具有挑戰(zhàn)性的一個問題,是一個程序異常(打斷程序運行,比如錯誤的保存了指令的結果),被中斷(來自處理器外的異常,比如內存的讀寫錯誤),就比如算術溢出。很多業(yè)內人士并不區(qū)分開兩者,都稱之為中斷。
那這些異常是如何處理的呢?為了對其進行處理,我們必須知道是那些指令引起的異常問題,目前有兩種方法,第一種需要一個狀態(tài)寄存器,其中有一個字段用于記
錄異常產生的原因。另一種方法利用向量中斷(用來控制轉換的終端地址)這兩種方式在這里我們不去展開細講,更多的是為了下面幾章做一點點鋪墊。
1.5 實例 奔騰處理器的內部架構
奔騰系列都是采用流水線設計,它讓多條指令重疊從而達到更高的指令吞吐率,其時鐘周期的長度有單個功能單元的延遲決定。這里我們暫且放一放,之后還會有詳解。
Intel的IA 32指令集(指CPU能識別什么類型的指令)非常復雜,是對其實現控制電路的一大難點,雖然核心內容都是源于前幾節(jié)的內容,但是想要出成品并不容易
IA 32的指令,有些可能用到幾十個周期,甚至超過幾百個周期的指令。例如,串行傳送指令要求計算并修改兩個不同的存儲地址,并且存儲一個字節(jié)串。而且他復雜的尋址模式也使其使其結構實現難度大大提高。
而Intel的工程師巧妙地運用多周期數據通路和微程序控制器(使用代碼而不是01來表示控制的方法),這樣,即使是需要周期數不同的指令,也會減少更多的周期損失(因為頻率是固定的)
1.6 奔騰4的結構
超標量,這是在奔騰4系列CPU中引入的一種技術,簡單來看,這種技術使得處理器可以有多條數據通路,每一條處理某一類型指令:存取指令,ALU計算,分
支。這樣處理器便可以在一個周期內執(zhí)行多條指令(當然這些都僅僅是皮毛,之后我們依舊會在第二大章進行討論)。而所謂的微操作,便是利用某種技術,讓每一
條指令分配給不同的數據通路,從而達到更高的效率。
在奔騰4中,蹤跡緩存技術就是來存儲微指令的,這是一種解決方案,記錄微指令將會被引入哪一條特定的數據通路。這種緩存技術比較復雜,我們會在第三大章中稍作了解。
奔騰4使用簡單的硬聯線控制和簡單數據通路,結合蹤跡緩存,獲得了令人吃驚的時鐘頻率,當然還要得益于深度流水線的引入,不過這都是后話了。
第二章 流水線,更高更快
2.1 流水線初涉
相信對于大多數了解硬件的朋友,流水線早已不是什么陌生的詞匯了,它并不難理解。
我們先回顧一下一般的數據通路如何處理指令,首先PC會將指令地址送給ALU,ALU進行處理將數據存儲,然后PC值加4
,這樣就可以進行下一個指令的處理。而流水線便是不間斷的發(fā)射指令,原本一個指令需要得到結果才會被處理,而現在則是讓指令充斥著整個數據通路,在ALU
處理第一條指令時,第二條指令已經進行取值,當第一條指令處理后,第二條指令立刻被送往ALU,這樣就減少了非常多的時鐘周期(一個指令需要經過取指令,
訪問寄存器,ALU操作,訪問數據,訪問寄存器這五步)(再次進行解釋,第二步中的訪問寄存器是讓ALU得到操作數據,第四步訪問數據也就是得到ALU的
計算結果所必須的一些數據,例如a+b,我們需要知道a和b的值是多少。而訪問寄存器就是對PC的操作)如果這樣說還不明白的話,我們簡單打個比方,我們
做飯,需要先把菜做好,然后去煮米飯,而流水線話操作時,我們可以一邊煮米飯,一邊做菜,這樣就減少了整個做飯的時間。而假設煮米飯要10分鐘,做菜要
20分鐘,那么整個流水化操作后就需要20分鐘,也就是說流水線操作的時間取決于需要時間最長的事情,在CPU中就是任務的執(zhí)行周期數取決于最復雜,處理
速度最慢的指令(比如一個超長浮點運算)
附言:流水線增加的是CPU指令的吞吐率,而不是減少了單個指令執(zhí)行的時間,而且因為某些特殊的問題,還會讓單個指令執(zhí)行時間增加,例如流水線寄存器的引入
2.2 流水線結構的冒險
我想當看完2.1節(jié)后大家一定會說,流水線竟然如此簡單?確實流水線并不難理解,但是真正實現過程中人們發(fā)現了相當多的問題,會引起流水線的處理停頓,我們稱為冒險。
結構冒險
這是第一種冒險,即硬件不支持多條指令在同一個時鐘周期內執(zhí)行。比如我們做菜的時候,因為家里的電器因為線路的原因只能工作一個,那么我們只能先煮米飯,再做菜了。
如果用CPU角度來考慮的話,如果在流水線中一個指令在該周期內需要從內存中取得數據,而同時另一條指令需要寫入內存,這樣,因為DDR內存在一個周期內
只能執(zhí)行一次讀或者寫操作(數據總線只有一條,而對于GDDR3之后的顯示卡內存,因為具備多條數據總線,可以對內存同時進行讀寫操作)那么這兩條指令就
造成了結構冒險。
數據冒險
這是第二種冒險,在一個操作必須等待另一操作完成后才能進行時,那么就會造成流水線停頓。例如我們需要知道a和b,需要將兩個數相加得到c的值,之后再對
c進行立即數操作(直接對數值進行加減乘除運算,而不需要讀取被加數的寄存器地址),那么必須等a和b相加后得到的數據寫到寄存器中才可以進行下一個操
作。
控制冒險
第三種冒險,當處理器需要根據一條指令的結果作出決策,此時其他的指令可能在執(zhí)行中。好比一個分支操作,我們需要知道是執(zhí)行分支中哪一條指令才能進行下一步操作,這樣接下來的指令就需要得到分支的結果才能進行處理。
10月5日 抱歉,昨天有點事。。。。。。
2.2 有問題就要解決
既然流水線有那么多限制,為何不去簡化它呢?或者說直接不流水。可是經過很多科學家的驗證,流水線對程序提升的性能即使存在如此多的冒險,依舊客觀,根據流水線加速比的公式,一個5步驟處理的CPU可以提升3~4倍的性能(實則5倍,但是因為有冒險)
不去解決流水線的冒險可以嗎?對于像GPU這種高度并行,數據之間關聯度低(也就是流水線的冒險度較低,不易發(fā)生流水線停頓)我們完全沒有必要去理會,不過
通過對指令并行的提升(ILP Instruction-Level-Parallelism )比如co-issue(相信關注GPU核心的朋友對這個
詞都會有所了解),讓兩個完全沒有關聯的數據進行流水操作從而提升性能,當然就目前來看ILP已經走到了盡頭。
而CPU則不然,因為我們運行的程序關聯性較大,如果依舊無解決辦法直接流水,那么損失的時鐘周期是相當恐怖的,那么我們就來簡單談談CPU設計中是如何減少這種冒險的。
數據旁路:這是一種解決數據冒險的方法,它使用內部的數據緩存直接提供缺少的數據,而不需等待該數據到達程序員可見的寄存器或內存才使用。實現它,需要用到直通技術。
為了直觀,我們先舉一個簡單的例子,a+b=c,c+d=f,我們知道了a,b,d的值,要得到c的數據才能相加。首先我們的CPU會先計算出c的值,這時
候利用直通技術,將c的值直接傳給下一個指令,而不需要等到該指令結束后由PC將地址發(fā)送,那么下一條指令也便無需等待,直接可以計算。
重排指令:這里我們需要用一個簡單的例子,我們需要計算a,b,而a=c+d,b=c+e,需要的數據都在寄存器上,因為要流水,那么就要重復獲取c的值,
如果對這段高級語言進行編譯,那么因為c的值需要在一個周期內取得兩次(在正常編譯后是這種情況),所以就會發(fā)生冒險。如果我們對加載c值的順序進行調
整,就可以避免沖突。這也可以叫做亂序執(zhí)行,也就是out of order
分支預測與分支延遲:這都是用來解決控制冒險的,因為需要得到分支的結果才可以進行下一步,那么在一些流水級超長的CPU中(比如奔騰4)會造成相當大的周期損失。分支預測,很簡單,就是通過某種方式對分支的結果進行預測,那么我們也便無需等待分支的結果是真是假,直接執(zhí)行下一步便可。分支延遲也很簡單,我們先不理會分支的結果如何,對分支的兩種可能都進行運算,等到分支得到結果之后再舍棄。
目前流行的都是分支預測,這里拆開還能將非常多,比如BTB,我們會在下幾節(jié)進行深入探討.
10月6日
2.4 流水線的數據通路
首先,作為進階的思考,我們還是回顧一下一般的單周期數據通路,我們經典的5階段的CPU,分為IF取指令,ID指令譯碼(編譯),EX指令執(zhí)行,MEM
數據內存訪問,WB寫回。如果用5階段的CPU進行流水,那么任意周期內,都會有一條指令充滿這5個階段,那么為了讓指令能夠得到不間斷的發(fā)射,我們必須
增加更多的寄存器,當一條指令經過一個階段后馬上讓PC值加上4,從而發(fā)射下一條指令,所以我們采取的方式是,在每個階段之間都要加上流水線寄存器,比如
在IF和ID段中加入一個寄存器,那么該寄存器的作用便是得到IF的指令值,反饋,使得PC值加4,而且它還要做指令數據傳輸的工作,也就是將IF的數值
傳送給ID段。那么流水線寄存器的頻率就一定要是流水線本身頻率的兩倍,所以在一個周期中,前半段時間讓PC值加上4,后半段則是傳送數據給下一個階段。
附錄:superpipeline 超長流水線。
超長流水線,也稱深度流水線,它是一種高級流水線技術,在這里我們簡單來探討一下。
首先要指出的是,超長流水線并不是指ALU更多的流水線。它的含義是將一個較短階段(stage)的流水線劃分成更多階段。
其實在我一開始接觸的時候也不明白,為什么劃分更多階段能給予良好的流水性能呢?其實這一點不難理解,因為這樣,在一個周期內流水線內部的指令數會比原來
更多,同樣因為劃分的更加細,頻率也更容易提升(因為流水線的頻率取決于速度最慢的那一階段),這樣,在計算大量數據時,這種超長流水線就可以得到很好的
加速效果,但是,若是出現冒險,那么損失的時鐘周期是非??膳碌?。P4當中引入了大量的緩存(cache),目的就是讓指令所需的數據能在cache中得
到而不去等待慢吞吞的內存(目前內存的頻率都是200,DDR運用了DIMM上下沿并發(fā)和數據預取的技術從而等效達到了高頻率,但是一個1.8G的CPU
依舊需要9個周期去等待內存數據)P4能達到較高的頻率,也很大程度上依靠了這種高級流水線技術。
國慶最后一天特別專題(今后2周上課所以無法更新= =)
高級話題:性能的再次提升
流水線的開發(fā),同樣造就了一個概念,叫做指令集并行,。主要通過兩種方式提高指令集的并行能力一個是增加流水線技術,另一種則是設計更多的內部元件從而在 一個流水線中的每級發(fā)射更多的指令。前者我們已經有所探討,他就是P4中引入的superpipeline。后者就包括超標量設計,涉及到了流水線的寬 度。
我們現在深入探討第二個話題。這種多發(fā)射技術,目前有兩種比較聰明的實現方法,他們的區(qū)別就是編譯器和硬件之間如何分工,由于分工主要在于某些決定是在編譯期決定的還是在運行期決定的,所以前者稱之為靜態(tài)多發(fā)射,后者叫做動態(tài)多發(fā)射。
靜態(tài)多發(fā)射處理器利用編譯期從而對指令進行打包和處理各種特殊的流水線冒險,在靜態(tài)多發(fā)射中,我們可以將多條指令看作一條超長指令,復雜指令。同樣,因為 本身可以看作一條超長指令,那么它便被固定了長度,操作數。這就是所謂的VLIW,超長指令字,相信對R600了解的朋友一定不會陌生。
動態(tài)多發(fā)射處理器也被稱之為超標量處理器,在比較簡單的模型中,指令是按照順序發(fā)射,每個周期可以發(fā)射1條或多條指令,或者說不發(fā)射。非常明顯的是,這種 處理器要達到較好的性能非常依靠編譯期對各條指令的調節(jié),錯開指令之間的依賴關系從而達到更高的發(fā)射速率。所以目前超標量處理器會更多的在指令排序方面下 工夫。
附錄:多發(fā)射處理器的數據通路
非常簡單,我們只需要在一般的多周期數據通路上增加更多的執(zhí)行單元,比如ALU,對各種單元進行劃分,比如A單元執(zhí)行浮點,B單元執(zhí)行整數,通過對寄存器的大小調節(jié),便可以適應不同的指令。
第二章,完
第三章 層次結構存儲器
1 導論
假如你是在做高數作業(yè),為了快速計算,你會把積分表放在最顯眼的地方,其次為了防止對一些積分變換的不熟練,你會放一個例題本在一旁,這樣又不會的變換就可以直接查。而如果有一個題你怎么也做不出來,就值得去求教老師。
其實本來作業(yè)應該是我們自己做的,實在不會就去請教老師,但是借助了積分表和積分變換的例題就能更快的解決題目,而不需要去請教老師,因為請教老師太麻煩
太慢了。這樣,在CPU當中也存在這種類似的環(huán)境,也就是說最能幫助你解決當前問題(指令最需要的數據)的應該優(yōu)先拜訪(優(yōu)先訪問),再或者說你有兩本詞
典,一本是英語5000實用詞,另一本是牛津高階英漢詞典,查單詞的時候,我們當然會先去查看實用詞詞典咯,大辭典查起來太慢了。
下面就得引入必備的理論知識了
時間局部性:如果一個數據項被引用,那在不久之后它很有可能再次使用。比如在第一個例子中,比如一個循環(huán)指令,每次循環(huán)都需要一個常量B,那么B就非常容易被調用
空間局部性:如果某個數據項被引用,那么不久之后與它地址相近的數據項可能會被引用,也就是說數據間有相依性啦
層次結構存儲器,也就是按照這兩種原理所衍生的。現在的計算機就有緩存和內存之分(寄存器不屬于層次結構存儲器,它的目的是存儲目前需要使用的數據,而不
是可能會使用到的數據,切記切記),緩存小而快速,一般都在CPU的uncore部分,內存就很容易理解了,在緩存和硬盤之間的,速度和容量在兩者之間其
緩沖的東東。為什么速度快容量就要小呢?這是一個邏輯電路的知識,簡單的來說就是為了得到更高的速度,那信號的發(fā)射頻率必須提升,而為了得到更大的容量,
那么就必須保證信號傳輸中減少干擾。如果頻率提高,干擾就會增強,所以兩者比較難以統(tǒng)一。
存儲器的層次結構可以由多級組成,但是數據復制每次必須在兩個相鄰層次間才可以進行,一個層次結構中存儲信息的最小單元,我們稱之為快或行
(line,cache
line,眼熟吧)如果處理器需要的數據出現在高層(速度快,容量小的cache)的塊中,測稱之為一次命中,而命中率就是指我們需要的數據在cache
中所占的比例。缺失率也就是cache中沒有的數據占需求數據的百分比。
10月24日
1.2 緩存的簡單基礎知識
cache,這是專業(yè)的叫法,其實就是一種層次結構罷了,早期的緩存都屬于片外緩存,也就是集成在主板上的,現在的緩存都會放到CPU的Uncore中,
也就是非核心模塊,cache本身屬于一種超高速內存(可以如此理解),但是本身卻和內存有較大的差距,因為cache屬于高速量小的存儲器,那么如何合
理利用這分寶貴的資源就是人們必須要掌握的了。
我們先來討論一個比較簡單的情況,假設內存中存儲了1到10十個數據,如果我們這時候讀取其中的4號數據,那么cache將會立刻將3,4,5這些數據調
入,因為根據之前我們所講的時間空間局部性,這些臨近的數據和數據本身都是很有可能被再次用到(數據第一次讀取是去內存找而不是緩存,術語叫做強制性沖
突,下一次會有講到哦)再來說一個,如果cache中有1~10數據中的3,4,5,如果CPU需要6號數據,而cache中沒有,那么5,6,7數據就
會立即調入cache,根據局部性原理。
這時候追求細節(jié)的朋友們可能會提問,CPU怎么知道cache中有沒有所需的數據呢?如果在,又是如何找到的呢?最簡單的方法就是給內存的每一個數據
(字)分配一個緩存的地址,每一個內存的數據地址對應一個確定的緩存地址(數據重復),也就是說,當我們讀取內存發(fā)現cache中含有該數據那么就會去
cache中尋找,從而縮短的很多時間。這種簡單的分配方式叫做直接映像。由于每個緩存的地址可對應的內存中多個不同地址,怎么才能知道所請求的數據是否
在緩存中呢?這就得引入標記這個概念了,標記必須包含能夠判斷緩存中的數據是否為所請求數據的地址信息。我們還需要一種辦法來判斷緩存中的確沒有有效的信
息,我們就必須知道緩存中部分標記要被忽略,最常用的方法就是有效位,說明一個cache塊中是否有有效地址。如果這個位置沒有設置,就不能讀取其內容。
1.3高速緩存的缺失
在接下來討論實際系統(tǒng)的高速緩存之前,我們現在看一看控制部件是如何處理cache miss的。首先呢,我們必須通過控制器檢測到缺失的發(fā)生,然后從低一級的緩存或內存中取出相應的數據,如果高速緩存命中,CPU繼續(xù)照常處理,就好像什么事情都沒有發(fā)生。
命中時,處理器的控制方法的修改并不太重要,而缺失時就必須附加一些工作了。cache的缺失處理由兩部分協(xié)同完成,一個是處理器的控制器,另一個就是進
行初始化內存訪問和重新填充緩存的獨立緩存控制器。高速緩存的缺失導致流水線停頓(去看第二章),與流水線中斷不同(比如你運行QQ,結果突然間把它關掉
了),中斷發(fā)生時,系統(tǒng)要求保存所有寄存器的狀態(tài),而缺失發(fā)生時,我們在等待主存操作完成的期間,可以使整個機器停頓,本質上就是凍結臨時寄存器和程序員
可見的寄存器(學編程吧,否則我講了也不會明白)的內容,而緩存的缺失只是流水線停頓的一種情況,所以也是非常簡單的。
作為硬件討論的基礎我們依然要討論一下對于多周期或流水線的數據通路(進階,必須把第一章的看完),指令發(fā)生缺失時將如何處理?如果去一條指令導致缺失。
那么指令寄存器的內容無效。為了把正確的指令取到高速緩存中,必須讓存儲器執(zhí)行一次讀操作,由于是在流水線中,在指令執(zhí)行的第一個周期,程序計數器加一個
增量,因此產生高速緩存指令缺失的指令地址等于程序計數器減4.一旦有了地址,就可以只是主存執(zhí)行一次讀操作,之后等待存儲器的相應,然后把數據寫入高速
緩存。
說了這么多估計大家都已經暈掉了,下面我們再來條理地回顧一下高速緩存去指令缺失的處理步驟
1 把最初PC的值送到存儲器
2 指示主存執(zhí)行讀操作
3 寫高速緩存,把從存儲器中讀到的數據寫入高速緩存的數據部分,把地址的高位寫入標記域,設置有效位
4 重啟第一步,它將重新取指令,這次發(fā)現指令在高速緩存中。
1.4 寫操作
寫操作稍微有些不同。假設有一個存儲指令,我們只把數據寫入高速緩存,那么寫入高速緩存后,主存和高速緩存相應位置的值將會變化。在這種情況下,高速緩存
和主存稱為不一致。保持一致的最簡單方法就是在緩存和主存中都寫入數據,也就是寫通過(write through)。
盡管這種方法十分簡單,但是并不能提供良好的性能,所以,寫緩沖(write
buffer)就出現了。當一個數據在等待被寫入主存時,先把它存放在緩沖器中。在把數據寫入高速緩存和寫緩沖后,處理器繼續(xù)執(zhí)行指令。當寫入主存操作結
束后,寫緩沖里的內容也將被釋放。如果寫緩沖滿了,那么當處理器執(zhí)行到一個寫操作時,就得先停下來知道寫緩沖有一個空的位置。當然,如果存儲器完成寫操作
的速度比處理器的速度慢,怎么緩沖也沒有用。
寫通過機制還有一種變通的方法是寫回(write back),采用寫回的方法,當一個寫操作產生時,新的數據僅僅被寫道高速緩存的塊中,只有當修改過的塊被替換時,才把它寫到底層的存儲結構中去。
附言:其實還有很多很多操作方式,我累了。。。。。只是說了說常見的。。。。。。
11月8日發(fā)燒,帶病堅持= =低調
(實在不忍心繼續(xù)停下了,順便打算給圖形學簡單開個頭,希望大家捧個場)
1.5 塊的定位方式與cache缺失
一直到現在,我們討論的將塊放入cache中,都是用最簡單的定位方式,即一個塊只能放到高速緩存中的一個位置,也就是直接映射(因為存儲器中任何一個塊
的地址都被直接映射到更高層的cache中),事實上強大的工程師們還有非常多的方式來安排塊,直接映射屬于一種極端,一個塊就是直接映射,這時一個塊被
精確的放在一個位置中。
另一種極端方式則是,一個塊可以放在cache中的任何位置。這種方式就是所謂的全相聯(因為存儲器中的塊可以和cache中的任何一塊聯系)。在全相聯
的cache中要找一個給定的塊,由于該塊可能被放在任何位置,必須檢測高速緩存的所有項。為了使檢測更加簡潔,它是由與cache中美向相關的一個比較
器并行處理完成的,這些比較器增大了晶體管的開銷,因為全相聯只是用那些塊的數量較少的cache。
介于兩種極端的設計叫做組相聯。在一個組相聯的cache中,每個塊可以被放在固定數量(2個以上)的位置上,每個塊有n個位置可以放的組相聯cache
被稱為n路組相聯cache。。一個n路的組相聯cache有許多組構成,每個組中都有n個塊,存儲器的每個塊由下標域對應到cache中唯一的組,并可
以放在此組中的任何一個塊上。因此組相聯映射是把直接映射和全相聯映射結合起來的妥協(xié)措施,這樣每個塊可以直接映射到一個組,然后檢測該組中的所有塊是否
匹配。
將這么多有毛用?大家別急,現在我們再次回顧一下之前的東東。
在直接映射中,一個存儲塊的位置是如下給出的:
塊號——cache中塊的個數
而組相聯則是:
塊號——cache中組的個數
由于全相聯中所需要的塊可以放在任何地方,所以要檢測cache中所有塊的所有標記。
而組相聯的塊可以被放在組中的任何一個位置,所以不許檢測該組中所有的塊標記。
直接映射的cache可以看作一個簡單的1路組相聯;每個cache的一個項為一個塊,形成只有一個塊的組。有n項的全相聯cache可以看作是一個n路的組相聯cache,它只有一個組,組中有m個塊,每一項可以放在該組中的任何一個塊中)
提高關聯度的優(yōu)點是它可以提升cache的命中率,但是卻增加了命中時間,也加大了比較器的開銷。
備注:我們所說的塊就是cache line
就是這樣,命中率并不僅僅決定于緩存的容量,這是一個非常普遍的錯誤認知,cache相聯度同樣與處理器本身有一定關系。
終章 Pentium P4 與AMD Opteron的存儲器
這一章大概就是CPU設計原理的最后一節(jié)了,為了做一個完美的謝幕,當然要用大家最關心的實際問題來結尾啦!
皓龍和奔騰在新的架構中肯定會對一個重要的細節(jié)進行修補,那就是我們這一章節(jié)詳細討論的cache,兩者都附加有優(yōu)化措施來提升命中率。首先是在缺失時先 返回被請求的數據,如先前小節(jié)中所描述的。二者都允許處理器在cache缺失期間,繼續(xù)執(zhí)行訪問數據cache的指令,這一技術被稱為無阻塞cache, 經常被工程師們用在亂序執(zhí)行(看第二章去)的處理器上,來隱藏cache的缺失延遲。這種技術實現無阻塞有兩個特點,第一就是指令與其他的工作來隱藏一部 分缺失延遲,第二就是重疊兩個不同缺失的延遲。
要重疊多重cache缺失的大部分缺失時間需要較高帶寬的存儲系統(tǒng)來并行的處理多重缺失,事實上這一點也被用在GPU中(當任務一在處理時,因為需要尋找 數據所以會有延時,如果在任務一尋找數據的同時執(zhí)行任務二,那么這一部分延時就會被隱藏掉,同樣正因如此,GPU才被稱之為高度并行處理器,另外,這種技 術也可以在CUDA編程中應用從而提高GPU的通用計算能力)。
奔4和皓龍的處理器都要預取指令(TLB的一種技術,有些深,沒講的一部分),也都采用內部包含的硬件預取機制來訪問數據。他們觀察數據缺失的模式,并利用此信息預測下一次取指令的信息,在循環(huán)訪問時效果很好(循環(huán)指令)。
對于微處理器的設計者們面臨的最嚴峻的挑戰(zhàn)之一,就是支持像P4和皓龍這種每個周期可以執(zhí)行多條存儲器指令的處理器(超標量啊,別告訴我你忘了)。有兩種 不同的技術可以支持一級cache中的多個請求。cache可以是多端口的,允許對同一cache塊的多個訪問同時進行。但是多端口cache一般非常昂 貴,因為多端口存儲器中的RAM單元比單端口中的單元大得多(在具體說,單端口的塊不能在同一時間進行多次操作,再多端口中增加了塊的數量)。另外一種方 案是把cache分成段,并允許多個互相獨立的存取操作對兩個不同的段進行訪問。
關于細節(jié):AMD和Intel芯片的最大區(qū)別也許就是P4指令cache使用了蹤跡cache,而AMD皓龍使用的是更加傳統(tǒng)的指令cache。
不同于順序的將指令裝入一個cache塊中以增加空間局部性,蹤跡cache將找到的動態(tài)的包括所有分支的指令裝入一個cache塊。這樣cache塊中 包含的就是有CPU決定的執(zhí)行指令的動態(tài)記錄,而不是主存局部決定的靜態(tài)指令序列。由于cache中帶有分支預測,我們必須確認分支以及地址的有效性,以 保證有效的去指令。另外P4的cache中存的是為指令而不是皓龍的IA 32指令。
很明顯,蹤跡cache需要更為復雜的cache地址映射機制,因為地址已經不再是對齊的了。
然而蹤跡cache可以提高cache塊的利用率。例如,在傳統(tǒng)的cache中,有分支轉跳到另一個很大的塊中,這樣塊的開始一部分占用的空間就可能不被 訪問到。同樣,由分支轉跳可能跳出這樣的塊,那么塊的最后一部分就很可能被浪費掉了。蹤跡cache僅僅存儲分支入口到離開記錄之間的指令,這樣避免了頭 尾的浪費。當然這樣也有一個弊端就是他可能在cache中多次存儲相同的指令,條件分支的不同選擇結構導致了相同的指令成為了多個蹤跡的一部分,而每一部 分都會存儲在cache中。