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