程序員學習 CPU 有什麼用?

前言

大家好,我是小彭。

在上一篇文章裏,我們聊到了計算機的馮·諾依曼架構,以及計算機的五大部件:控制器、運算器、存儲器、輸入設備和輸出設備。在現在計算機體系中,CPU 是整個計算機的核心,主要包含控制器和運算器兩大部件。

在後續文章中,我們將從 CPU 的基本認識開始,逐步將 CPU 與執行系統、存儲系統 和 I/O 系統串聯起來,請關注。


思維導圖:


1. 認識 CPU 中央處理器

1.1 什麼是 CPU?

中央處理單元(Central Processing Unit,CPU)也叫中央處理器或主處理器,是整個計算機的核心,也是整臺計算機中造價最昂貴的部件之一。

從硬件的角度: CPU 由超大規模的晶體管組成;

從功能的角度: CPU 內部由時鐘、寄存器、控制器和運算器 4 大部分組成。

  • 1、時鐘(Clock): 負責發出時鐘信號,也可以位於 CPU 外部;
  • 2、寄存器(Register): 負責暫存指令或數據,位於存儲器系統金字塔的頂端。使用寄存器能夠彌補 CPU 和內存的速度差,減少 CPU 的訪存次數,提高 CPU 的吞吐量;
  • 3、控制器(Control Unit): 負責控制程序指令執行,包括從主內存讀取指令和數據發送到寄存器,再將運算器計算後的結果寫回主內存;
  • 4、運算器(Arithmetic Logic Unit,ALU): 負責執行控制器取出的指令,包括算術運算和邏輯運算。

馮·諾依曼架構

—— 圖片引用自 Wikipedia

1.2 爲什麼要學習 CPU?

對於大部分程序員,日常所處理的工作都是在跟 Java 和 C++ 等高級語言打交道,並不會直接地與 CPU 打交道。那麼,爲什麼我們還要花這麼多時間去學習 CPU 呢?我認爲有以下原因:

  • 原因 1 - 掌握 CPU 原理能夠開發更高性能的程序: 理解 CPU 的工作原理有助於設計出更高性能的算法或代碼,例如通過避免僞共享、提高緩存命中率等方式提高程序運行效率,就需要對 CPU 的緩存機制有一定的理解;

  • 原因 2 - 擴展方案積累: CPU 是整個計算機系統中最複雜的模塊,也是當代計算機科學的制高點。積累 CPU 內部的解決方案,能夠爲將來的遇到類似問題提供思路,達到觸類旁通的作用。例如 CPU 緩存淘汰策略與應用內存的緩存淘汰策略有相似之處;

  • 原因 3 - CPU 是知識體系最底層的知識: 當我們在思考或解決某一個問題時,就需要利用到更深層次的知識積累來解釋,而 CPU 就是位於知識體系中最底層知識。例在內存系統的可見性、執行系統的 IO_WAIT 和線程池設計等問題中,都需要對 CPU 的執行機制有一定理解。

CPU

—— 圖片引用自 圖片來源

1.3 通用處理器和專用處理器

在早期的計算機系統中,只有 1 個通用處理器,使用 1 個處理器就能夠完成所有計算任務。後來人們發現可以把一些計算任務分離出來,單獨設計專門的芯片微架構,在執行效率上會遠遠高於通用處理器,最典型的專用處理器就是 GPU 圖形處理器。

這種用來專門處理某種計算任務的處理器就是專用處理器,那爲什麼專用處理器在處理某些特定問題時更快呢,我認爲有 3 點解釋:

  • 1、最優架構: 專用處理器只處理少量類型的工作,可以爲特定工作設計最優芯片架構,而通用處理器只能設計全局最優架構,但不一定是執行特定工作的最優機構;
  • 2、硬件加速: 可以把多條指令的計算工作直接用硬件實現,相比於 CPU 一條條地執行指令,能夠節省大量指令週期;
  • 3、成本更低: 專用處理器執行的計算流程是固定的,不需要 CPU 的流水線控制、亂序執行等功能,實現相同計算性能的造價更低。

現代計算機架構都是 1 個通用處理器加上多個專用處理器,這種將不同類型的計算任務採用不同的計算單元完成的設計,也叫 異構計算(Heterogeneous Computing)。

多處理器架構


2. 指令集架構 ISA

2.1 什麼是指令集架構?

CPU 所能理解的機器語言就是 指令(Instruction Code), 一個 CPU 所能理解的所有指令就是 指令集(Instruction Set)。

爲了保證芯片間的兼容性,芯片廠商並不爲每款新芯片設計一個新的指令集,而是將指令集推廣爲標準規範,這個規範就是 指令集架構(Instruction Set Architecture,ISA)

相對於指令集架構,CPU 在實現具體指令集功能的硬件電路設計就是 微架構(Micro Architecture)。 如果用軟件的思考方式,ISA 就是 CPU 的功能接口,定義了 CPU 的標準規範,而微架構就是 CPU 的功能實現,定義了 CPU 的具體電路設計,一種指令集可以兼容不同的微架構。

2.2 兩種主流的指令集架構

因爲 CPU 位於整個計算機系統最底層且最核心的部件,如果 CPU 的兼容性都出問題了,那麼以前開發的應用軟件甚至操作系統將無法在新的 CPU 上運行,這對芯片廠商的生態破壞是致命的。因此,指令集架構是相對穩定的,芯片廠商在 ISA 中添加或刪除指令時會非常謹慎。

目前,能夠有效佔領市場份額的只有 2 個 ISA ,它們也分別代表了複雜與精簡 2 個發展方向:

  • x86 架構: Intel 公司在 1970 年代推出的複雜指令集架構;
  • ARM 架構: ARM 公司在 1980 年代推出的精簡指令集架構,我們熟悉的 Apple M1 芯片、華爲麒麟芯片和高通驍龍芯片都是 ARM 架構(其實,ARM 公司並不生產芯片,而是以技術授權的模式運行)。

2.3 複雜指令集和精簡指令集

在 CPU 指令集的發展過程中,形成了 2 種指令集類型:

  • 複雜指令集(Complex Instruction Set Computer,CISC): 強調單個指令可以同時執行多個基本操作,用少量指令就可以完成大量工作,執行效率更高;
  • 精簡指令集(Reduced Instruction Set Computer,RISC): 強調單個指令只能執行一個或少數基礎操作,指令之間沒有重複或冗餘的功能,完成相同工作需要使用更多指令。

在早期的計算機系統中,指令集普遍很簡單,也沒有複雜和精簡之分。隨着應用軟件的功能越來越豐富,應用層也在反向推動芯片架構師推出更強大的指令集,以簡化程序編寫和提高性能。例如,一些面向音視頻的指令可以在一條指令內同時完成多個數據進行編解碼。

這在當時的確是不錯的選擇。 原因是 CPU 和主存的速度差實在太大了,用更少的指令實現程序功能(指令密度更高)可以減少訪存次數。 憑藉這一點,複雜指令集對精簡指令集的優勢是幾乎全面性的:

  • 優勢 1: 可以減少程序佔用的內存和磁盤空間大小;
  • 優勢 2: 可以減少從內存或磁盤獲取指令所需要的帶寬,能夠提高總線系統的傳輸效率;
  • 優勢 3: CPU L1 Cache 可以容納更多指令,可以提高緩存命中率。且現代計算機中多個線程會共享 L1 Cache,指令越少對緩存命中率越有利;
  • 優勢 4: CPU L2 Cache 可以容納更多數據,對操作大量數據的程序也有利於提高緩存命中率。

然而,這些優勢都是有代價的:

  • 缺點 1 - 處理器設計複雜化: 指令越複雜,用於解析指令的處理器電路設計肯定會越複雜,執行性能功耗也越大;
  • 缺點 2 - 指令功能重疊: 很多新增的指令之間產生了功能重疊,不符合指令集的正交性原則,而且新增的很多複雜指令使用率很低,但處理器卻付出了不成正比的設計成本;
  • 缺點 3 - 指令長度不統一: 指令長度不統一,雖然有利於使用哈夫曼編碼進一步提高指令密度(頻率高的指令用短長度,頻率高的指令用大長度),但是指令長度不同,執行時間也有長有短,不利於實現流水線式結構。

因此,到 1980 年代,精簡指令集 RISC 逐漸浮出水面。目前,大多數低端和移動系統都採用 RISC 架構,例如 Android 系統、Mac 系統和微軟 Surface 系列。

相比於複雜指令集,精簡指令集更加強調 “正交性” ,單個指令只能執行一個或少數基礎操作,指令之間沒有重複或冗餘的功能。而且精簡指令集的每條 指令長度相同 ,非常便於實現流水線式結構。

網上很多資料有一個誤區: 精簡指令集簡化了指令集的大小。 這是不對的,準確的說法是簡化了指令集的複雜度。

總結一下: 複雜指令集憑藉更高的指令密度,在性能方面整體優於精簡指令集(內存 / 磁盤佔用、CPU Cache 命中率、TLB 未命中率),而精簡指令集犧牲了指令密度換取更簡單的處理器架構,以性能換取功耗的平衡。

指令集類型 CISC RISC
指令數量 指令數量龐大 指令數量相對較少
指令長度 長度不同 長度相同
指令功能 有重疊 正交
舉例 x86 ARM、MIPS

3. CPU 的性能指標

3.1 執行系統參數

  • 1、主頻(Frequency/Clock Rate): 在 CPU 內部有一個 晶體振盪器(Oscillator Crystal) ,晶振會以一定的頻率向控制器發出信號,這個信號頻率就是 CPU 的主頻。主頻是 CPU 最主要的參數,主頻越快,計算機單位時間內能夠完成的指令越快。 CPU 的主頻並不是固定的,CPU 在運行時可以選擇低頻、滿頻甚至超頻運行, 但是工作頻率越高,意味着功耗也越高;

  • 2、時鐘週期(Clock Cycle): 主頻的另一面,即晶振發出信號的時間間隔, 時鐘週期=1/主頻;

  • 3、外頻: 外頻是主板爲 CPU 提供的時鐘頻率,早期計算機中 CPU 主頻和外頻是相同的,但隨着 CPU 主頻越來越高,而其他設備的速度還跟不上,所以現在主頻和外頻是不相等的;

  • 4、程序執行時間:

    • 4.1 流逝時間(Wall Clock Time / Elapsed Time): 程序開始運行到程序結束所流逝的時間;

    • 4.2 CPU 時間(CPU Time): CPU 實際執行程序的時間,僅包含程序獲得 CPU 時間片的時間(用戶時間 + 系統時間)。由於 CPU 會並行執行多個任務,所以程序執行時間會小於流逝時間;

    • 4.3 用戶時間(User Time): 用戶態下,CPU 切換到程序上執行的時間;

    • 4.4 系統時間(Sys Time): 內核態下,CPU 切換到程序上執行的時間;

3.2 存儲系統參數

  • 字長(Word): CPU 單位時間內同時處理數據的基本單位,多少位 CPU 就是指 CPU 的字長是多少位,比如 32 位 CPU 的字長就是 32 位,64 位 CPU 的字長就是 64 位;

  • 地址總線寬度(Address Bus Width): 地址總線傳輸的是地址信號,地址總線寬度也決定了一個 CPU 的尋址能力,即最多可以訪問多少數據空間。舉個例子,32 位地址總線可以尋址 4GB 的數據空間;

  • 數據總線寬度(Data Bus Width): 數據總線傳輸的是數據信號,數據總線寬度也決定了一個 CPU 的信息傳輸能力。

區分其它幾種容量單位:

  • 字節(Byte): 字節是計算機數據存儲的基本單位,即使存儲 1 個位也需要按 1 個字節存儲;

  • 塊(Block): 塊是 CPU Cache 管理數據的基本單位,也叫 CPU 緩存行;

  • 段(Segmentation)/ 頁(Page): 段 / 頁是操作系統管理虛擬內存的基本單位。

相關文章: 計算機的存儲器金字塔長什麼樣?


4. 影響 CPU 性能的因素

CPU 作爲計算機的核心部件,未來一定是朝着更強大的性能出發。在看待 CPU 的視角上,我們也要具備一定的全局觀:

  • 1、提升 CPU 性能不止是 CPU 的任務: 計算機系統是多個部件組成的複雜系統,脫離整體談局部沒有意義;
  • 2、平衡性能與功耗: 一般來說,CPU 的計算性能越高,功耗也越大。我們需要綜合考慮性能和功耗的關係,脫離功耗談性能沒有意義。

4.1 提升 CPU 主頻

提升主頻對 CPU 性能的影響是最直接的,過去幾十年 CPU 的主要發展方向也是在怎麼提升 CPU 主頻的問題上。

不過,最近幾年 CPU 主頻的速度似乎遇到瓶頸了。因爲想要主頻越快,要麼讓 CPU 滿頻或超頻運行,要麼升級芯片製程,在單位體積裏塞進去更多晶體管。這兩種方式都會提升 CPU 功耗,帶來續航和散熱問題。如果不解決這兩個問題,就無法突破主頻瓶頸。

主頻的瓶頸

—— 圖片引用自 Wikipedia

4.2 多核並行執行

既然單核 CPU 的性能遇到瓶頸,那麼在 CPU 芯片裏同時塞進去 2 核、4 核甚至更多,那麼整個 CPU 芯片的性能不就直接翻倍提升嗎?

理想很美好,現實是性能並不總是隨着核心數線性增加。在覈心數較小時,增加並行度得到的加速效果近似於線性提升,但增加到一定程度後會趨於一個極限, 說明增加並行度的提升效果也是有瓶頸的。

爲什麼呢?因爲不管程序並行度有多高,最終都會有一個結果彙總的任務,而彙總任務無法並行執行,只能串行執行。例如,我們用 Java 的 Fork/Join 框架將一個大任務分解爲多個子任務並行執行,最終還是需要串行地合併子任務的結果。

這個結論也有一個經驗定律 —— 阿姆達爾定律(Amdahl’s Law) ,它解釋了處理器並行計算後效率提升情況。我們把串行的部分稱爲串行分量 W_s ,把並行的部分稱爲並行分量 W_p ,正是串行分量限制了性能提升的極限,串行分量越大,極限越低。

  • 並行後的執行時間是 \frac{W_p}{p} + W_s
  • 並行後的加速倍數是 \frac{W_s+W_p}{W_s+\frac{W_p}{p}} ,當並行度 p 趨向於 無窮大時,提升極限就是 \frac{W_s+W_p}{W_s}

並行度、並行分量對提升效果的影響

—— 圖片引用自 Wiki 百科

說明: 以綠色的曲線爲例,程序可以的並行分量是 95%,串行分量是 5%,最終得出的提升極限就會 20 倍。

4.3 指令重排序

增加核心數是提升並行度最直接的方法,但並不是唯一的方法。

現代 CPU 爲了提高並行度,會在遵守單線程數據依賴性原則的前提下,對程序指令做一定的重排序。事實上不止是 CPU,從源碼到指令執行一共有 3 種級別重排序:

  • 1、編譯器重排序: 例如將循環內重複調用的操作提前到循環外執行;
  • 2、處理器系統重排序: 例如指令並行技術將多條指令重疊執行,或者使用分支預測技術提前執行分支的指令,並把計算結果放到重排列緩衝區(Reorder Buffer)的硬件緩存中,當程序真的進入分支後直接使用緩存中的結算結果;
  • 3、存儲器系統重排序: 例如寫緩衝區和失效隊列機制,即是可見性問題,從內存的角度也是指令重排問題。

指令重排序類型

相關文章: 12 張圖看懂 CPU 緩存一致性與 MESI 協議,真的一致嗎?

4.4 SoC 芯片 —— 片內片外雙總線結構

隨着芯片集成電路工藝的進步,在馮·諾依曼架構中的五大部件(運算器、控制器、存儲器、輸入和輸出設備接口)也可以集成在一個芯片上,形成一個近似於完整計算機的系統,這種芯片也叫 片上系統(System on Chip,Soc)。 SoC 芯片將原本分佈在主板上的各個部件聚合到同一個芯片上,不同部件之間的總線信息傳輸效率更高。

相關文章: 圖解計算機內部的高速公路 —— 總線系統


5. 總結

今天,我們簡單了討論了 CPU 的基本概念,很多問題只是淺嘗輒止。在後續的文章裏,我們將從執行系統、存儲系統 和 I/O 系統三個角度與 CPU 串聯起來。請關注。


參考資料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章