
算是讀書筆記吧
極客時間--深入淺出計算機組成原理
最簡單的 CPU

1. 首先,我們有一個自動計數(shù)器
這個自動計數(shù)器會隨著時鐘主頻不斷地自增,來作為我們的 PC 寄存器。
2. 在這個自動計數(shù)器的后面,我們連上一個譯碼器
譯碼器還要同時連著我們通過大量的 D 觸發(fā)器組成的內(nèi)存。
3. 自動計數(shù)器會隨著時鐘主頻不斷自增
從譯碼器當中,找到對應的計數(shù)器所表示的內(nèi)存地址,然后讀取出里面的 CPU 指令。讀取出來的 CPU 指令會通過我們的 CPU 時鐘的控制,寫入到一個由 D 觸發(fā)器組成的寄存器,也就是指令寄存器當中。
4. 在指令寄存器后面,我們可以再跟一個譯碼器
這個譯碼器不再是用來尋址的了,而是把我們拿到的指令,解析成 opcode 和對應的操作數(shù)。
5. 執(zhí)行具體指令
當我們拿到對應的 opcode 和操作數(shù),對應的輸出線路就要連接 ALU,開始進行各種算術和邏輯運算。
對應的計算結(jié)果,則會再寫回到 D 觸發(fā)器組成的寄存器或者內(nèi)存當中。
指令周期(Instruction Cycle)
計算機每執(zhí)行一條指令所需要的一次循環(huán),就叫指令周期
計算機每執(zhí)行一條指令的過程,可以分解成這樣幾個步驟:
1.Fetch(取得指令)
由控制器(Control Unit)操作
也就是從 PC 寄存器里找到對應的指令地址,根據(jù)指令地址從內(nèi)存里把具體的指令,加載到指令寄存器中,然后把 PC 寄存器自增,好在未來執(zhí)行下一條指令。
2.Decode(指令譯碼)
由控制器(Control Unit)操作
也就是根據(jù)指令寄存器里面的指令,解析成要進行什么樣的操作,是 R、I、J 中的哪一種指令,具體要操作哪些寄存器、數(shù)據(jù)或者內(nèi)存地址。
3.Execute(執(zhí)行指令)
由算術邏輯單元(ALU),也就是運算器進行操作。
也就是實際運行對應的 R、I、J 這些特定的指令,進行算術邏輯操作、數(shù)據(jù)傳輸或者直接的地址跳轉(zhuǎn)。
不過,如果是一個簡單的無條件地址跳轉(zhuǎn),那么我們可以直接在控制器里面完成,不需要用到運算器。
指令寄存器
存放當前正在執(zhí)行的指令,包括指令的操作碼,地址碼,地址信息
PC 寄存器
存放著下一條指令的地址
也叫程序計數(shù)器,是用來計數(shù)的,指示指令在存儲器的存放位置,也就是個地址信息。
各種函數(shù)調(diào)用、條件跳轉(zhuǎn)。其實只是修改 PC 寄存器里面的地址。
PC 寄存器里面的地址一修改,計算機就可以加載一條指令新指令,往下運行。
譯碼器
- 無論是對于指令進行 decode
- 根據(jù)內(nèi)存地址去獲取對應的數(shù)據(jù)或者指令
運算器
可以完成數(shù)據(jù)的存儲、處理和傳輸?shù)膯卧?。通常由兩部分組成:
-
操作元件
ALU,也叫組合邏輯元件(Combinational Element)
在特定的輸入下,根據(jù)不同組合電路的邏輯,生成特定的輸出。
-
存儲元件
也叫狀態(tài)元件
比如我們在計算過程中需要用到的寄存器,無論是通用寄存器還是狀態(tài)寄存器,其實都是存儲元件。
控制器
機械地重復“Fetch - Decode - Execute“循環(huán)中的前兩個步驟,然后把最后一個步驟,通過控制器產(chǎn)生的控制信號,交給 ALU 去處理
時序邏輯電路
任意時刻的輸出僅僅取決于該時刻的輸入,與電路原來的狀態(tài)無關。
類似加減乘除法器
時序邏輯電路
任意時刻的輸出不僅取決于當時的輸入信號,而且還取決于電路原來的狀態(tài),或者說,還與以前的輸入有關。
也就是我們說的記憶功能。
最常見的這個電路就是我們的 D 觸發(fā)器,它也是我們實際在 CPU 內(nèi)實現(xiàn)存儲功能的寄存器的實現(xiàn)方式。
這也是現(xiàn)代計算機體系結(jié)構(gòu)中的“馮·諾伊曼”機的一個關鍵,就是程序需要可以“存儲”,而不是靠固定的線路連接或者手工撥動開關,來實現(xiàn)計算機的可存儲和可編程的功能。
流水線設計
通過將一個CPU指令的執(zhí)行步驟,拆分成多個小步驟的方式。達到縮短單個時鐘周期的目的。
單指令周期處理器
在一個時鐘周期里,確保執(zhí)行完一條最復雜的 CPU 指令,也就是耗時最長的一條 CPU 指令
如果 PC 寄存器自增地太快,程序就會出錯。
因為前一次的運算結(jié)果還沒有寫回到對應的寄存器里面的時候,后面一條指令已經(jīng)開始讀取里面的數(shù)據(jù)來做下一次計算了。
這個時候,如果我們的指令使用同樣的寄存器,前一條指令的計算就會沒有效果,計算結(jié)果就錯了。
這樣做的弊端是,無論是執(zhí)行一條用不到 ALU 的無條件跳轉(zhuǎn)指令,還是一條計算起來電路特別復雜的浮點數(shù)乘法運算,我們都等要等滿一個時鐘周期。
指令流水線
每個步驟獨立運作,不需要等待整條指令執(zhí)行完畢的這種協(xié)作方式,將原本串行起來的幾個步驟并行執(zhí)行。叫做指令流水線。
CPU 本身的設計,是由一個個獨立的組合邏輯電路串接起來形成的,天然能夠適合這樣采用流水線“專業(yè)分工”的工作方式。

-
流水線級(Pipeline Stage)
每一個獨立的步驟,我們就稱之為流水線階段或者流水線級(Pipeline Stage)。
如果我們把一個指令拆分成“取指令 - 指令譯碼 - 執(zhí)行指令”這樣三個部分,那這就是一個三級的流水線。
如果我們進一步把“執(zhí)行指令”拆分成“ALU 計算(指令執(zhí)行)- 內(nèi)存訪問 - 數(shù)據(jù)寫回”,那么它就會變成一個五級的流水線。
-
這樣,我們不需要確保最復雜的那條指令在時鐘周期里面執(zhí)行完成,而只要保障一個最復雜的流水線級的操作,在一個時鐘周期內(nèi)完成就好了。
如果某一個操作步驟的時間太長,我們就可以考慮把這個步驟,拆分成更多的步驟,讓所有步驟需要執(zhí)行的時間盡量都差不多長。這樣,也就可以解決我們在單指令周期處理器中遇到的,性能瓶頸來自于最復雜的指令的問題。像我們現(xiàn)代的 ARM 或者 Intel 的 CPU,流水線級數(shù)都已經(jīng)到了 14 級。
超長流水線
-
Pentium 4與Athlon的CPU大戰(zhàn)
流水線設計帶來的性能提升也引出了現(xiàn)代桌面 CPU 的最后一場大戰(zhàn),也就是 Intel 的 Pentium 4 和 AMD 的 Athlon 之間的競爭
在技術上,這場大戰(zhàn) Intel 可以說輸?shù)梅浅氐?,Pentium 4 系列以及后續(xù) Pentium D 系列所使用的 NetBurst 架構(gòu)被完全拋棄,退出了歷史舞臺。但是在商業(yè)層面,Intel 卻通過遠超過 AMD 的財力、原本就更大的市場份額、無所不用的競爭手段,以及最終壯士斷腕般放棄整個 NetBurst 架構(gòu),最終依靠新的酷睿品牌戰(zhàn)勝了 AMD。
在此之后,整個 CPU 領域競爭的焦點,不再是 Intel 和 AMD 之間的桌面 CPU 之戰(zhàn)。在 ARM 架構(gòu)通過智能手機的快速普及,后來居上,超越 Intel 之后,移動時代的 CPU 之戰(zhàn),變成了高通、華為麒麟和三星之間的“三國演義”。
那 2000 年發(fā)布的 Pentium 4 的流水線深度是多少呢?答案是 20 級,比 Pentium III 差不多多了一倍,而到了代號為 Prescott 的 90 納米工藝處理器 Pentium 4,Intel 更是把流水線深度增加到了 31 級。
-
超長流水線的弊端
- 功耗問題
需要的寄存器變多。主頻的提升和晶體管數(shù)量的增加都使得我們 CPU 的功耗變大了。 - 依賴問題很難解決
過長的流水線使得任務之間的依賴處理復雜度成指數(shù)級的增長。
三大冒險
任何一本講解 CPU 的流水線設計的教科書,都會提到流水線設計需要解決的三大冒險,分別是
結(jié)構(gòu)冒險(Structural Hazard)、數(shù)據(jù)冒險(Data Hazard)以及控制冒險(Control Hazard)
結(jié)構(gòu)冒險
結(jié)構(gòu)冒險,本質(zhì)上是一個硬件層面的資源競爭問題,也就是一個硬件電路層面的問題。
CPU 在同一個時鐘周期,同時在運行兩條計算機指令的不同階段。但是這兩個不同的階段,可能會用到同樣的硬件電路。
最典型的例子就是內(nèi)存的數(shù)據(jù)訪問,訪存(MEM)和取指令(Fetch)都要進行內(nèi)存數(shù)據(jù)的讀?。?/p>

訪存(MEM)和取指令(Fetch)都要進行內(nèi)存數(shù)據(jù)的讀取。而我們的內(nèi)存,只有一個地址譯碼器的作為地址輸入,無法同時進行這兩件事。
普林斯頓架構(gòu)(Princeton Architecture)也就是馮·諾依曼體系結(jié)構(gòu)的內(nèi)存結(jié)構(gòu)如圖所示

這其實和薄膜鍵盤的“鎖鍵”問題一樣。
常用的最廉價的薄膜鍵盤,并不是每一個按鍵的背后都有一根獨立的線路,而是多個鍵共用一個線路。如果我們在同一時間,按下兩個共用一個線路的按鍵,這兩個按鍵的信號就沒辦法都傳輸出去。
這也是為什么,重度鍵盤用戶,都要買貴一點兒的機械鍵盤或者電容鍵盤。因為這些鍵盤的每個按鍵都有獨立的傳輸線路,可以做到“全鍵無沖”。
哈佛架構(gòu)(Harvard Architecture)
把我們的內(nèi)存分成兩部分,讓它們各有各的地址譯碼器。這兩部分分別是存放指令的程序內(nèi)存和存放數(shù)據(jù)的數(shù)據(jù)內(nèi)存。

現(xiàn)代CPU的混合架構(gòu)
現(xiàn)代的 CPU 雖然沒有在內(nèi)存層面進行對應的拆分,卻在 CPU 內(nèi)部的高速緩存部分進行了區(qū)分,把高速緩存分成了指令緩存(Instruction Cache)和數(shù)據(jù)緩存(Data Cache)兩部分。

我們的內(nèi)存雖然沒有按照功能拆分,但是在高速緩存層面進行了拆分,也就是拆分成指令緩存和數(shù)據(jù)緩存這樣的方式,從硬件層面,使得同一個時鐘下對于相同資源的競爭不再發(fā)生。
數(shù)據(jù)冒險
然而還有很多冒險問題,是程序邏輯層面的事兒。其中,最常見的就是數(shù)據(jù)冒險。
數(shù)據(jù)冒險,其實就是同時在執(zhí)行的多個指令之間,有數(shù)據(jù)依賴的情況。這些數(shù)據(jù)依賴,我們可以分成三大類:
- 先寫后讀(Read After Write,RAW),也叫數(shù)據(jù)依賴。
- 先讀后寫(Write After Read,WAR),也叫反依賴。
- 寫后再寫(Write After Write,WAW),也較輸出依賴。
流水線停頓(Pipeline Stall)
也叫流水線冒泡(Pipeline Bubbling),在存在依賴的情況下,讓流水線“再等等“。
這個存在依賴的情況,確切來講是:
我們在進行指令譯碼的時候,會拿到對應指令所需要訪問的寄存器和內(nèi)存地址。所以,在這個時候,我們能夠判斷出來,這個指令是否會觸發(fā)數(shù)據(jù)冒險。

不過,我們并不是讓流水線停下來,而是在執(zhí)行后面的操作步驟前面,插入一個 NOP 操作,也就是執(zhí)行一個其實什么都不干的操作。

需要注意的是我們不僅要在當前指令里面,插入 NOP 操作,所有后續(xù)指令也要插入對應的 NOP 操作。
就像一路縱隊,前邊有人停下系鞋帶,后邊所有人都得原地踏步踏,不然就得踩著腦袋過去了。
不過,流水線停頓這樣的解決方案,是以犧牲 CPU 性能為代價的。因為,實際上在最差的情況下,我們的流水線架構(gòu)的 CPU,又會退化成單指令周期的 CPU 了。
操作數(shù)前推(Operand Forwarding)
也較操作數(shù)旁路,更合適的名字應該叫操作數(shù)轉(zhuǎn)發(fā)。當
后一個操作S2的執(zhí)行依賴前一個操作S1的執(zhí)行結(jié)果,此時直接將S1的結(jié)果數(shù)據(jù)傳輸給S2的ALU進行處理。

- 當只用流水線冒泡進行處理時:
我們的第 2 條指令,其實多花了 2 個時鐘周期,運行了兩次空轉(zhuǎn)的 NOP 操作。

- 操作數(shù)前推進行處理時:
它越過(Bypass)了寫入寄存器,再從寄存器讀出的過程,也為我們節(jié)省了 2 個時鐘周期。

轉(zhuǎn)發(fā)(Forwarding),其實是這個技術的邏輯含義。
旁路(Bypassing),則是這個技術的硬件含義。為了能夠?qū)崿F(xiàn)這里的“轉(zhuǎn)發(fā)”,我們在 CPU 的硬件里面,需要再單獨拉一根信號傳輸?shù)木€路出來,使得 ALU 的計算結(jié)果,能夠重新回到 ALU 的輸入里來。這樣的一條線路,就是我們的“旁路”。
- 操作數(shù)前推+流水線冒泡進行處理時:
有的時候,雖然我們可以把操作數(shù)轉(zhuǎn)發(fā)到下一條指令,但是下一條指令仍然需要停頓一個時鐘周期。

有些時候,我們的操作數(shù)前推并不能減少所有“冒泡”,只能去掉其中的一部分。我們?nèi)匀恍枰ㄟ^插入一些“氣泡”來解決冒險問題。
亂序執(zhí)行
不以編譯的代碼順序為
指令執(zhí)行階段的順序,通過一個類似線程池的保留站,在保證不破壞數(shù)據(jù)依賴的前提下讓系統(tǒng)自己去動態(tài)調(diào)度先執(zhí)行哪些指令。彌補了 CPU 和內(nèi)存之間的性能差異,可以充分利用 CPU 的性能。
以下這個例子:
a = b + c
d = a * e
x = y * z
第三步計算其實完全不依賴前兩步,但是卻要在流水線中等待前兩步執(zhí)行完成。
其實我們完全可以將第三步提前執(zhí)行。所以在第二條指令等待第一條指令的訪存和寫回階段的時候,第三條指令就已經(jīng)執(zhí)行完成了。

-
內(nèi)亂外序
指令不再是順序執(zhí)行的,而是根據(jù)池里所擁有的資源,以及各個任務是否可以進行執(zhí)行,進行動態(tài)調(diào)度。在執(zhí)行完成之后,又重新把結(jié)果在一個隊列里面,按照指令的分發(fā)順序重新排序。即使內(nèi)部是“亂序”的,但是在外部看起來,仍然是井井有條地順序執(zhí)行。
在亂序執(zhí)行的情況下,只有 CPU 內(nèi)部指令的執(zhí)行層面,可能是“亂序”的。只要我們能在指令的譯碼階段正確地分析出指令之間的數(shù)據(jù)依賴關系,這個“亂序”就只會在互相沒有影響的指令之間發(fā)生。
即便指令的執(zhí)行過程中是亂序的,我們在最終指令的計算結(jié)果寫入到寄存器和內(nèi)存之前,依然會進行一次排序,以確保所有指令在外部看來仍然是有序完成的。
控制冒險
對于if…else 這樣的條件分支,或者 for/while 循環(huán),指令無法順序執(zhí)行。為了確保能取到正確的指令,之后的取指令和指令譯碼就會被打斷,等待之前的判斷邏輯來決定后面要執(zhí)行的指令。
縮短分支延遲
本質(zhì)上和前面數(shù)據(jù)冒險的操作數(shù)前推的解決方案類似,就是在硬件電路層面,把一些計算結(jié)果更早地反饋到流水線中。這樣反饋變得更快了,后面的指令需要等待的時間就變短了。
我們可以將條件判斷、地址跳轉(zhuǎn),都提前到指令譯碼階段進行,而不需要放在指令執(zhí)行階段。
對應的,我們也要在 CPU 里面設計對應的旁路,在指令譯碼階段,就提供對應的判斷比較的電路。
不過,他仍然不夠快:
在流水線里,第一條指令進行指令譯碼的時鐘周期里,我們其實就要去取下一條指令了。這個時候,我們其實還沒有開始指令執(zhí)行階段,自然也就不知道比較的結(jié)果。
靜態(tài)分支預測
最簡單的分支預測技術,叫作“假裝分支不發(fā)生”。
顧名思義,自然就是仍然按照順序,把指令往下執(zhí)行。
如果分支預測是正確的
我們節(jié)省下來本來需要停頓下來等待的時間如果分支預測失敗了
那我們就把后面已經(jīng)取出指令已經(jīng)執(zhí)行的部分,給丟棄掉。
這個丟棄的操作,在流水線里面,叫作 Zap 或者 Flush。
CPU 不僅要執(zhí)行后面的指令,對于這些已經(jīng)在流水線里面執(zhí)行到一半的指令,我們還需要做對應的清除操作。
比如,清空已經(jīng)使用的寄存器里面的數(shù)據(jù)等等,這些清除操作,也有一定的開銷。
所以,CPU 需要提供對應的丟棄指令的功能,通過控制信號清除掉已經(jīng)在流水線中執(zhí)行的指令。
只要對應的清除開銷不要太大,我們就是劃得來的。

動態(tài)分支預測
根據(jù)之前條件跳轉(zhuǎn)的比較結(jié)果來預測下一次比較結(jié)果。
-
一級分支預測(One Level Branch Prediction)
也叫 1 比特飽和計數(shù)(1-bit saturating counter)。
用一個比特,記錄當前分支的比較情況,直接用當前分支的比較情況,來預測下一次分支時候的比較情況。

如果前一天下雨,那么今天就會下雨:
這個表格里一共有 31 天,那我們就可以預測 30 次。你可以數(shù)一數(shù),按照這種預測方式,我們可以預測正確 23 次,正確率是 76.7%,比隨機預測的 50% 要好上不少。
-
雙模態(tài)預測器(Bimodal Predictor)
也叫2 比特飽和計數(shù)。
在一級分支預測的基礎上,用多個前置狀態(tài),預測當前的分支??梢酝ㄟ^引入一個狀態(tài)機來達到目的。

連續(xù)發(fā)生兩次相同狀態(tài),才改變狀態(tài)機的狀態(tài):
預測的結(jié)果的正確率會是 22 次,也就是 73.3% 的正確率。
這個方法雖然簡單,但是卻非常有效。在 SPEC 89 版本的測試當中,使用這樣的飽和計數(shù)方法,預測的準確率能夠高達 93.5%。
Intel 的 CPU,一直到 Pentium 時代,在還沒有使用 MMX 指令集的時候,用的就是這種分支預測方式。
-
for循環(huán)中的預測冒險

Time spent in first loop is 5ms
Time spent in second loop is 15ms
其他提升CPU性能的技術
超標量
正常的流水線情況下,我們只能讓CPU在指令執(zhí)行階段可以并行處理。但是一個時鐘周期內(nèi),也只能讀取一條指令。
超標量技術,通過添加硬件一次讀取多條指令的方式,讓CPU的IPC(一個時鐘周期里面能夠執(zhí)行的指令數(shù),代表CPU的吞吐率)超過了1。
-
多發(fā)射
我們同一個時間,可能會同時把多條指令發(fā)射(Issue)到不同的譯碼器或者后續(xù)處理的流水線中去。
-
超標量
本來我們在一個時鐘周期里面,只能執(zhí)行一個標量(Scalar)的運算。在多發(fā)射的情況下,我們就能夠超越這個限制,同時進行多次計算。

超線程
是一個“線程級并行”的解決方案。它通過讓一個物理 CPU 核心,“裝作”兩個邏輯層面的 CPU 核心,使得 CPU 可以同時運行兩個不同線程的指令
超線程技術一般也被叫作同時多線程(Simultaneous Multi-Threading,簡稱 SMT)技術。
在一個物理 CPU 核心內(nèi)部,會有雙份的 PC 寄存器、指令寄存器乃至條件碼寄存器。

我們并沒有增加真的功能單元。所以超線程只在特定的應用場景下效果比較好。
一般是在那些各個線程“等待”時間比較長的應用場景下。
比如,我們需要應對很多請求的數(shù)據(jù)庫應用,就很適合使用超線程。各個指令都要等待訪問內(nèi)存數(shù)據(jù),但是并不需要做太多計算。
SIMD(Single Instruction Multiple Data)單指令多數(shù)據(jù)流
一種“指令級并行”的加速方案,或者我們可以說,它是一種“數(shù)據(jù)并行”的加速方案。
對于那些在計算層面存在大量“數(shù)據(jù)并行”(Data Parallelism)的計算中,使用 SIMD 是一個很劃算的辦法。在這個大量的“數(shù)據(jù)并行”,其實通常就是實踐當中的向量運算或者矩陣運算。
在實際的程序開發(fā)過程中,過去通常是在進行圖片、視頻、音頻的處理。最近幾年則通常是在進行各種機器學習算法的計算。
正是 SIMD 技術的出現(xiàn),使得我們在 Pentium 時代的個人 PC,開始有了多媒體運算的能力??梢哉f,Intel 的 MMX、SSE 指令集,和微軟的 Windows 95 這樣的圖形界面操作系統(tǒng),推動了 PC 快速進入家庭的歷史進程。

-
并行讀取
Intel 在引入 SSE 指令集的時候,在 CPU 里面添上了 8 個 128 Bits 的寄存器。128 Bits 也就是 16 Bytes ,也就是說,一個寄存器一次性可以加載 4 個整數(shù)。
-
并行計算
4 個整數(shù)各自加 1,互相之前完全沒有依賴,也就沒有冒險問題需要處理。只要 CPU 里有足夠多的功能單元,能夠同時進行這些計算,這個加法就是 4 路同時并行的,自然也省下了時間。
手機CPU霸主--ARM
CISC--復雜指令集(Complex Instruction Set Computing)
使用類似赫夫曼編碼(Huffman coding)的方式,將機器指令進編碼。常用的指令要短一些,不常用的指令可以長一些。
雖然馮·諾依曼高屋建瓴地提出了存儲程序型計算機的基礎架構(gòu),但是實際的計算機設計和制造還是嚴格受硬件層面的限制。當時的計算機很慢,存儲空間也很小。《人月神話》這本軟件工程界的名著,講的是花了好幾年設計 IBM 360 這臺計算機的經(jīng)驗。IBM 360 的最低配置,每秒只能運行 34500 條指令,只有 8K 的內(nèi)存。為了讓計算機能夠做盡量多的工作,每一個字節(jié)乃至每一個比特都特別重要。
所以,CPU 指令集的設計,需要仔細考慮硬件限制。為了性能考慮,很多功能都直接通過硬件電路來完成。為了少用內(nèi)存,指令的長度也是可變的。就像算法和數(shù)據(jù)結(jié)構(gòu)里的赫夫曼編碼(Huffman coding)一樣,常用的指令要短一些,不常用的指令可以長一些。那個時候的計算機,想要用盡可能少的內(nèi)存空間,存儲盡量多的指令。
RISC--精簡指令集(Reduced Instruction Set Computing)
把指令“精簡”到 20% 的簡單定長指令,讓軟件來實現(xiàn)復雜de硬件的功能。
CPU 的整個硬件設計就會變得更簡單了,在硬件層面提升性能也會變得更容易了:
-
更多的通用寄存器
因為 RISC 完成同樣的功能,執(zhí)行的指令數(shù)量要比 CISC 多,所以,如果需要反復從內(nèi)存里面讀取指令或者數(shù)據(jù)到寄存器里來,那么很多時間就會花在訪問內(nèi)存上。
-
更好的分支預測
RISC 的 CPU 也可以把更多的晶體管,用來實現(xiàn)更好的分支預測等相關功能
-
RISC 降低了 CPU 硬件的設計和開發(fā)難度
從 80 年代開始,大部分新的 CPU 都開始采用 RISC 架構(gòu)。從 IBM 的 PowerPC,到 SUN 的 SPARC,都是 RISC 架構(gòu)
微指令架構(gòu)
從 Pentium Pro 時代開始,Intel 就開始在處理器里引入了微指令(Micro-Instructions/Micro-Ops)架構(gòu)。
讓 CISC 風格的指令集,在譯碼是翻譯成RISC風格,用 RISC 的形式在RISC架構(gòu)的CPU 里面運行

-
將CISC指令,轉(zhuǎn)化成多條RISC的微指令執(zhí)行
在微指令架構(gòu)里,我們的指令譯碼器相當于變成了設計模式里的一個“適配器”(Adaptor)。這個適配器,填平了 CISC 和 RISC 之間的指令差異。
-
用緩存,替代譯碼器。提升性能
Intel 就在 CPU 里面加了一層 L0 Cache。這個 Cache 保存的就是指令譯碼器把 CISC 的指令“翻譯”成 RISC 的微指令的結(jié)果。
于是,在大部分情況下,CPU 都可以從 Cache 里面拿到譯碼結(jié)果,而不需要讓譯碼器去進行實際的譯碼操作。這樣不僅優(yōu)化了性能,因為譯碼器的晶體管開關動作變少了,還減少了功耗。
使用“微指令”設計思路的 CPU,不能再稱之為 CISC 了,而更像一個 RISC 和 CISC 融合的產(chǎn)物。
ARM
ARM 這個名字現(xiàn)在的含義,是“Advanced RISC Machines”。
你從名字就能夠看出來,ARM 的芯片是基于 RISC 架構(gòu)的
-
手機端ARM能夠戰(zhàn)勝Intel的原因
1. 功耗優(yōu)先
一個 4 核的 Intel i7 的 CPU,設計的時候功率就是 130W。
而一塊 ARM A8 的單個核心的 CPU,設計功率只有 2W。兩者之間差出了 100 倍。
在移動設備上,功耗是一個遠比性能更重要的指標,畢竟我們不能隨時在身上帶個發(fā)電機。
ARM 的 CPU,主頻更低,晶體管更少,高速緩存更小,亂序執(zhí)行的能力更弱。
所有這些,都是為了功耗所做的妥協(xié)。
2. 低價
ARM 并沒有自己壟斷 CPU 的生產(chǎn)和制造,只是進行 CPU 設計,然后把對應的知識產(chǎn)權(quán)授權(quán)出去,讓其他的廠商來生產(chǎn) ARM 架構(gòu)的 CPU。
它甚至還允許這些廠商可以基于 ARM 的架構(gòu)和指令集,設計屬于自己的 CPU。像蘋果、三星、華為,它們都是拿到了基于 ARM 體系架構(gòu)設計和制造 CPU 的授權(quán)。ARM 自己只是收取對應的專利授權(quán)費用。多個廠商之間的競爭,使得 ARM 的芯片在市場上價格很便宜。
所以,盡管 ARM 的芯片的出貨量遠大于 Intel,但是收入和利潤卻比不上 Intel。
意在打造“CPU 屆的 Linux”的開源ARM架構(gòu)