前一篇計算機系統006 - 硬件組件之RAM中講完五大組件中的RAM部分,剩下最後的硬骨頭CPU還未說明,本篇就試着對其進行儘量完整的剖析。 編程
開篇以前,放一張CPU全貌鎮場。
緩存
工藝很好,封裝很完整,除了一排排針腳,再看不出來其餘東西,所幸透過外殼,一探究竟(以Intel Haswell爲例)。
函數
說實在的,要是不標英文註釋,我也不知道這裏面每一個區域放的是什麼。不過既然有,總比沒有好,這裏暫不討論商業化成熟的CPU方案全部內容,只關注以下兩個部分: post
SHARED L3 CACHE
若是還能記得上一期所述的存儲器層級圖的話,那麼你應該能注意到,SHARED L3 CACHE下面一級是MEMORY CONTROLLER IO,也就是說,這一級能夠視爲Cache,而下一級鏈接的是RAM,它的上一級又是CORE。因爲以前已經對Cache的來由和原理作了講解,這裏就不在贅述。性能
CORE
CORE其實是CPU的基礎計算單元(注意這裏說的是計算單元,而非控制單元或處理單元),它能夠運行單個進程,維護進程狀態、寄存器值、確保正確的執行次序,以及經過ALU執行操做。一個CPU一般由一至多個CORE,俗稱「多核」,上圖所示的CPU中就含有4個CORE,所以也稱4核。
既然每一個CORE能夠單獨運行進程,那麼在預算範圍內天然是越多越好。不過也應當知道,4核CPU總體性能並不能簡單換算成單核乘以4,先不論軟件上是否作了支持以即可以均攤在4核上跑滿,單說4核相互間也必須經過L3 Cache交換信息,就能夠知道在交換上會耗費一部分開銷。 優化
在第4篇 中介紹CPU部分時,給出了下面這張圖。
編碼
從圖中能夠看出,CPU是由ALU、CU、Memory三部分組成,而CORE能夠單獨執行整個進程,且CPU從一開始也是單核形式存在,因此這裏能夠等同認爲CORE也是由ALU、CU、Memory三部分組成。 操作系統
ALU也稱爲算術邏輯單元,是用於執行二進制表示整型的算術和按位運算組合數字電路。ALU是許多計算電路的基礎模塊,與之相對的是FPU(Floating-point unit)浮點單元,FPU處理的是浮點數值。 設計
以計算「1+2」爲例,其原理以下圖所示:
指針
Integer Operand A, B
A,B均爲輸入運算對象,分別爲 1(01),2(10)
Opcode
運算符,做用於運算對象。此處爲‘+’。雖然opcode與機器語言opcode在感念上有所區別,但一般會等同使用。
Status(可選)
可選狀態值,輸入輸出均爲狀態寄存器,在ALU進行計算時,可能須要參考其中標誌如CF判斷是否有進位,同時在結果中設置該flag
Integer Result
整型結果,輸出門電路交換後值,此處爲3(11)
包括上述加法操做,ALU一共支持以下類型操做:
每個Opcode都對應着不一樣的電路實現,相互間存在着邏輯門、觸發器等各類實現差別。而從ALU的使用原理上能夠看出,要想完成計算,需以下前提條件:
爲了提供這三類值,就必須先和寄存器打交道。
Register也稱爲寄存器,總的來說,Register是Memory中SRAM的一種,優點在於快,劣勢在於貴。
快的緣由在於無機械部件、無電容充放電,存取的全部過程均基於電路交換,也就是說電路頻率有多快,理論上他就能夠作到多快。不太高頻電路中不管是元器件焊點,仍是佈線都有可能對集成後電路總體性能和穩定性產生干擾,所以在頻率上也經常有所限制。
設計寄存器時,並不是全部Register都以相同電路實現,而是會以所要實現的功能爲目標進行取捨。一般,寄存器可分爲以下幾類:
MAR(Memory Address Register)
內存地址寄存器,保存數據或指令在內存中地址,掛載在地址總線上,用於在指令執行期間獲取數據或指令。例如CPU但願在內存中保存或獲取內存中某一數據時,可將對應地址放在MAR中
PC(Program Counter)
程序計數器,在Intel X86中也稱爲指令指針IP(instruction pointer),始終指向下一條要執行的指令。
AC(Accumulator) Register
累加寄存器,保存CPU計算所得結果。
MDR(Memory Data Register)
內存數據寄存器,與MAR相似,區別在於掛載在數據總線上。MDR就能夠從數據總線加載數據,也能夠存儲CPU中數據,就像一個Buffer同樣保存着送往解碼器(見1.3小節)前的信息。
MDR是配合MAR使用的,讀取某一內存地址數據前,如今MAR中存放讀取地址,發送讀信號,就能夠在MDR中獲取目標值;一樣在MAR中存入目標地址,MDR中存放要寫入數據後,發送寫信號,便可往內存中寫出數據。也就是說,MDR和MAR共同組成了CPU對內存部分的訪問接口。
Index Register
變址寄存器,存放從基址起要偏移的地址數,用於在程序運行過程當中調整操做符地址。
MBR(Memory Buffer Register)
緩存寄存器,存放已經讀取或寫入內存的數據或指令內容,起緩存做用。
Data Register
微型計算機中用於臨時存放傳輸給,或讀取自其餘外圍設備數據的數據。
固然,上述寄存器大可能是控制單元CU內部使用,對於用戶,可見的寄存器類型爲通用寄存器,以8086爲例,可見的寄存器以下:
累加寄存器 | AX |
基址寄存器 | BX |
計數寄存器 | CX |
數據寄存器 | DX |
棧指針寄存器 | SP |
基址指針寄存器 | BP |
源變址寄存器 | SI |
目的編制寄存器 | DI |
事實上,每一個寄存器的背後都有獨立的電路實現,而不一樣類型的寄存器實現每每各不相同。所以,編程時並不是強制讓你使用某個寄存器,而是因爲該寄存器設計時電路實現所限,它只支持部分功能。例如尋址時只能使用BX、BP、SI、DI,不是故意刁難,標新立異,而是由於只有這些寄存器在電路實現時對尋址作了支持。
一樣,一個進程運行後,會有對應狀態值,如指令指針、AF、CF、ZF等等標誌位,均存儲在對應寄存器中。CPU只會循環讀取下一條指令地址,進行計算,所以只要在讀取下一條指令地址前,將其替換成新進程的指令指針,便可完成進程切換。固然爲了確保能順利回來,還必須在替換前保存現有進程狀態。
到如今爲止,咱們有了支持不一樣運算操做(Opcode)的ALUs,也有了不一樣用途存儲不一樣數據的寄存器Registers,爲了實現進一步的自動化計算,應該開始考慮控制單元CU的內部邏輯了。
計算的實質是接收任務描述,按照任務描述的步驟,完成計算,並輸出結果。回到任務描述自己,用戶該如何描述一個任務以使得執行計算的計算機能夠理解任務內容?
想象一下現實生活中,須要將某一任務託付給別人時,咱們一般須要以下步驟:
當對方是計算機時,上述步驟就變成:
從前面咱們瞭解了ALU的運算方法和寄存器如何從內存中加載數據,所以這裏只考慮寄存器、ALU、CU三者之間的交互。對於此時的CU來說,寄存器中已經給出了可執行文件在內存中的入口地址,起點已經有了,接下來就是如何按照可執行文件內容順利執行完整個任務。
CU就像CPU的大腦,負責全部控制行爲。一般在CU內部,將計算任務執行過程分爲以下三步:
取指(Fetch)
第一步,獲取指令。程序內存中指令地址存儲在程序計數器PC中,每次獲取完指令後,PC自動加上所獲取到指令的長度,也就是指向下一條指令處。一般指令來源於相對較慢的內存中,這會阻塞CU直到獲取完成,好在現代處理器經過緩存或流水線技術極大緩解了該問題。
解碼(Decode)
第二步,指令解碼,指令解碼的最終解釋權歸CU指令集ISA全部。指令的一部分爲操做碼,標明應該執行何種操做。其他部分一般會提供該操做所需的額外信息,如操做數等。
CU實現分電路和微編程兩種,前者不可修改,但速度比微編程實現更快,因爲指令集修改後須要調整電路,代價較高,所以一般用於RISC精簡指令集中;另外一方面,微編程CU簡化告終構,下降了開發難度。
簡而言之,就是任務描述中的指令(以彙編級別起始)來源於CPU指令集,其中每條指令在從內存中讀取後進行解碼,解碼器將單條指令分解成一至多條微操做(Opcode),經過控制電路信號,選擇指定ALU完成目標操做。
同時,須要注意上述三個步驟執行過程當中須要參考時鐘脈衝,時鐘脈衝有特定頻率,電路被時鐘脈衝的上升沿或降低沿所觸發,造成統一步調。
上一節中對單個核心進行了探討,但隨着技術的發展,單核心的速度每每沒法知足日益增加的計算需求,所以在CPU發展史上,也陸續出現了以下改進技術。
流水線技術的前提是操做可進一步分解,分解後的每一個步驟可獨立運行。
不過須要注意的是,流水線技術並不能增長單個任務的處理效率,即每一個任務一樣仍是須要5個時鐘週期才能完成,甚至相反,反而會由於進行了任務分解而致使每一個步驟間需經過寄存器交換結果。
所以,從本質上來說,流水技術減小的是任務的平均等待時間,而非單個任務完成時間。
一般大的任務能夠分解爲小的任務,這樣就能夠同時進行處理以減小總體消耗時長。一般有以下3種並行計算方法:
位級別並行
經過增加處理器字長,減小了同一指令所需操做數目。如8位處理器在進行兩個16位整型數加法時,須要先將低8位相加,再將高8位及進位相加,也就是說,須要兩個操做才能實現一條指令。而若是使用16位處理器,就能夠經過一個操做完成相同指令。這樣一來,就減小了一半的執行時間。
指令級別並行
計算機程序其實就是一些列有序的指令,默認狀況下,處理器每一個時鐘週期內最多隻能處理一條指令,而事實上,有的指令從新排序後並列執行並不會影響最終結果,所以徹底能夠在指令級別實現部分並行以提升速度。
任務級別並行
同一程序的多個進程(程序運行實例,如感興趣,後續操做系統部分會講到)能夠針對相同數據或不一樣數據進行並行處理,甚至同一程序也能夠將其子任務分發給不一樣處理器進行處理。
改進至此,卻發現不管CPU如何優化並行、流水線等技術,真正致使程序執行速率緩慢的緣由還在於CPU每執行一條指令,至少要與存儲器交互一次,寄存器也好,內存也罷,它們的速率即便有了Cache或者分級存儲機制,依然不可以有效彌補。爲了可以最大限度地使用CPU,就須要對耗時嚴重的I/O操做進行優化。
傳統模型裏,執行一次I/O須要三個步驟:
從中能夠看出,第1、三個步驟並未直接參與主存讀寫,耗時遠比第二個步驟少,爲了減小第二個步驟所消耗的CPU資源,因而從硬件層引入了中斷機制。
中斷能夠經過單獨控制器實現,也能夠集成進CPU中。每一箇中斷有各自獨立的編碼,硬件上有具備相互獨立的內存單元。當一箇中斷出現後,控制器在執行完當前指令後將切換程序至內置ISR(Interrupt Service Routine)或指定的中斷處理程序,執行完畢後,再從新切回原執行程序。
至於如何完成CPU中斷的進程切換,將在後面詳細講述,此處只說明爲修改PC地址、從新載入進程被切換前各寄存器狀態值便可。
CPU這一篇就寫到這裏,沒有滿屏的電路圖,也沒有什麼高深的人與天然。我的看法來說,理解CPU本質仍是要回歸到計算自己,包括計算實現、計算表示、以及自動化計算流程的分解。但願可以有所收穫,到本篇爲止,硬件部分基本講完,然而有硬件並不能成爲計算機,因此下一篇中,將從操做系統開始提及。