來點有技術含量的 一款CPU如何設計和構建
本文由騰訊數碼獨家發布
我們都認為CPU是計算機的「大腦」,但這到底意味著什麼呢?你的電腦里有數十億個晶體管,這是怎麼回事?在這個新的四部分迷你系列,我們將集中在計算機硬體設計,涵蓋了什麼使計算機工作的里里外外。
該系列將涵蓋計算機架構、處理器電路設計、超大規模集成電路(VLSI)、晶元製造和未來的計算趨勢。如果您一直對處理器內部工作原理的細節感興趣,請繼續關注,因為這是你應該了解的內容。
我們將從一個非常高的層次開始,了解處理器的功能以及構建模塊如何在功能設計中組合在一起。這包括處理器內核、內存層次結構、分支預測等等。首先,我們需要一個CPU的基本定義。最簡單的解釋是CPU遵循一組指令對一組輸入執行某些操作。例如,可以從內存中讀取一個值,然後將其添加到另一個值,最後將結果存儲回內存的不同位置。如果之前的計算結果大於零,也可以是更複雜的,比如除以兩個數。
當你想要運行一個像操作系統或遊戲這樣的程序時,程序本身就是一系列CPU要執行的指令。這些指令從內存中載入,並在一個簡單的處理器上逐一執行,直到程序完成。當軟體開發人員用高級語言(如c 或Python)編寫程序時,處理器無法理解這一點。它只理解1和0,所以我們需要一種方法來表示這種格式的代碼。
作為指令集體系結構(ISA)的一部分,程序被編譯成一組稱為彙編語言的低級指令。這是CPU用來理解和執行的一組指令。一些最常見的ISAs是x86、MIPS、ARM、RISC-V和PowerPC。就像用c 編寫函數的語法與用Python編寫相同函數的語法不同一樣,每個ISA也有不同的語法。
這些ISAs可以分為兩大類:固定長度和可變長度。RISC-V ISA使用固定長度的指令,這意味著每條指令中一定數量的預定義位決定了它是哪種類型的指令。這與x86不同,x86使用可變長度指令。在x86中,指令可以用不同的方式編碼,不同部分的比特數也不同。由於這種複雜性,x86 cpu中的指令解碼器通常是整個設計中最複雜的部分。
固定長度的指令允許更容易的解碼,因為它們有規則的結構,但限制了ISA可以支持的總指令的數量。雖然普通版本的RISC-V架構有大約100條指令,而且是開源的,但是x86是專有的,沒有人真正知道有多少條指令。人們通常認為有幾千條x86指令,但確切的數字並不是公開的。儘管ISAs之間存在差異,但它們都具有本質上相同的核心功能。
現在我們準備好打開電腦,開始運行程序。指令的執行實際上有幾個基本部分,這些部分通過處理器的許多階段分解。
第一步是將指令從內存中取出到CPU中開始執行。在第二步中,指令被解碼,這樣CPU就可以知道它是什麼類型的指令。有很多類型,包括算術指令、分支指令和內存指令。一旦CPU知道它正在執行的指令類型,指令的操作數就會從CPU中的內存或內部寄存器中收集。如果你想把數字A加到數字B上,在你真正知道A和B的值之前,你不能做加法。大多數現代處理器是64位的,這意味著每個數據值的大小是64位。
64位是指CPU寄存器、數據路徑和/或內存地址的寬度。對於普通用戶來說,這意味著一台計算機一次可以處理多少信息,而對於它較小的架構表(32位),這是最容易理解的。64位體系結構一次可以處理兩倍的信息量(64位與32位)。
在CPU擁有指令的操作數之後,它將移動到執行階段,在此階段對輸入執行操作。這可以是添加數字,對數字執行邏輯操作,或者只是傳遞數字而不修改它們。計算結果之後,可能需要訪問內存來存儲結果,或者CPU可以將值保存在它的一個內部寄存器中。結果存儲後,CPU將更新各種元素的狀態,並繼續執行下一條指令。
當然,這種描述是一種極大的簡化,大多數現代處理器將把這幾個階段分解為20個或更多更小的階段,以提高效率。這意味著儘管處理器將在每個周期中啟動和完成多個指令,但是任何一條指令從開始到結束可能需要20個或更多的周期。這個模型通常被稱為管道,因為它需要一段時間來填充管道和液體完全通過它,但一旦它滿了,你得到一個恆定的輸出。
一條指令所經過的整個周期是一個非常嚴格編排的過程,但並非所有指令都可以同時完成。例如,加法非常快,而除法或從內存載入可能需要數百個周期。大多數現代處理器不是在一條緩慢的指令完成時使整個處理器停止工作,而是無序地執行。這意味著它們將確定在給定時間執行哪條指令最有益,並緩衝其他未準備好的指令。如果當前指令還沒有準備好,處理器可能會跳到代碼中,看看是否有其他指令已經準備好了。
除了無序執行之外,典型的現代處理器還採用了所謂的超標量體系結構。這意味著在任何時候,處理器都在管道的每個階段同時執行許多指令。它還可能等待數百人開始執行死刑。為了能夠同時執行許多指令,處理器將在每個管道階段中包含多個副本。如果處理器看到兩條指令已經準備好執行,並且它們之間沒有依賴關係,那麼它將同時執行這兩條指令,而不是等待它們分別完成。這種方法的一個常見實現稱為同步多線程(SMT),也稱為超線程。英特爾和AMD處理器目前支持雙向SMT,而IBM已經開發出支持多達8路SMT的晶元。
為了完成這種精心設計的執行,處理器除了基本核心之外還有許多額外的元素。處理器中有數百個單獨的模塊,每個模塊都有特定的用途,但是我們只討論基礎知識。兩個最大和最有益的是緩存和分支預測器。我們將不討論的其他結構包括重新排序緩衝區、註冊別名表和預訂站。
緩存的目的常常令人困惑,因為它們像RAM或SSD一樣存儲數據。緩存的不同之處在於它們的訪問延遲和速度。儘管RAM非常快,但對於CPU來說,它的速度慢了幾個數量級。RAM可能需要數百個周期才能對數據做出響應,處理器可能會陷入無事可做的境地。如果數據不在RAM中,訪問SSD上的數據可能需要數萬個周期。如果沒有緩存,我們的處理器就會停止工作。
處理器通常有三個層次的緩存,形成了所謂的內存層次結構。L1緩存是最小和最快的,L2在中間,L3是緩存中最大和最慢的。在層次結構中的緩存之上是小型寄存器,在計算期間存儲單個數據值。這些寄存器是系統中速度最快的存儲設備。當編譯器將高級程序轉換成彙編語言時,它將確定使用這些寄存器的最佳方法。
當CPU從內存中請求數據時,它將首先檢查該數據是否已經存儲在L1緩存中。如果是,則可以在幾個周期內快速訪問數據。如果它不存在,CPU將檢查L2,然後搜索L3緩存。緩存的實現方式通常是對核心透明的。核心只需要在指定的內存地址中請求一些數據,層次結構中的任何級別都將響應它。當我們進入內存層次結構的後續階段時,大小和延遲通常會增加幾個數量級。最後,如果CPU在任何緩存中都找不到它要查找的數據,那麼它就會進入主內存(RAM)。
在典型的處理器上,每個核心將有兩個L1緩存:一個用於數據緩存,一個用於指令緩存。L1緩存的總容量通常在100 kb左右,大小可能因晶元和代而異。每個核心通常都有一個L2緩存,儘管在某些體系結構中它可能在兩個核心之間共享。L2緩存通常是幾百kb。最後,在所有核心之間共享一個L3緩存,其大小為幾十兆位元組。
當處理器執行代碼時,它最常用的指令和數據值將被緩存。這大大加快了執行速度,因為處理器不需要不斷地進入主內存來獲取它需要的數據。在本系列的第2部分和第3部分中,我們將更多地討論如何實際實現這些內存系統。
除了緩存之外,現代處理器的另一個關鍵構件是精確的分支預測器。分支指令類似於處理器的「if」語句。如果條件為真,將執行一組指令,如果條件為假,將執行另一組指令。例如,您可能想比較兩個數字,如果它們相等,則執行一個函數,如果它們不同,則執行另一個函數。這些分支指令非常常見,大約佔程序中所有指令的20%。
從表面上看,這些分支指令似乎沒有什麼問題,但對於處理器來說,它們實際上非常具有挑戰性。因為在任何時候,CPU可能同時執行10條或20條指令,所以知道要執行哪條指令是非常重要的。可能需要5個周期來確定當前指令是否是分支,另外10個周期來確定條件是否為真。在此期間,處理器可能已經開始執行許多附加指令,甚至不知道這些指令是否正確。
漏洞:著名的Spectre攻擊利用分支預測和猜測中的bug。攻擊者將使用專門編寫的代碼使處理器推測性地執行會泄漏內存值的代碼。一些方面的猜測不得不重新設計,以確保數據不會泄漏,這導致性能略有下降。
在過去的幾十年里,用於現代處理器的體系結構已經取得了長足的進步。創新和巧妙的設計帶來了更好的性能和底層硬體的更好利用。不過,CPU製造商對其處理器中的技術非常保密,因此不可能確切知道其內部究竟發生了什麼。話雖如此,計算機工作的基本原理在所有處理器上都是標準化的。英特爾可能會增加他們的秘密武器,以提高緩存命中率或AMD可能會增加一個先進的分支預測器,但他們都完成相同的任務。
這是關於處理器工作原理的基本介紹。在下一部分中,我們將討論如何設計進入CPU的組件,包括邏輯門、時鐘、電源管理、電路原理圖等等,請繼續關注。
※奧林巴斯確認正在開發OM-D E-M5 III明星無反繼任者
※汽車在地面上比速度 未來飛行汽車應該怎麼比?
TAG:有趣的數碼 |