JOVANA
Explore Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

儲存程式概念與范紐曼模型

一個激進的想法——程式只是資料,與它所處理的數字一起住在同一塊記憶體裡——把電腦從一台要重新接線的機器變成了一台通用機器。本篇講這個想法所打造的模型,以及它誠實存在的裂縫。

從重新接線到記住程式

在第一篇你已看到,計算機結構研究的是如何把一堆開關,變成一台能跑人們實際寫出的程式的機器。最早的電子計算機是用最辛苦的方式跑程式:要改變機器做的事,工程師得親手重新插拔電纜、撥動成排的開關,耗上數小時甚至數天。機器與程式是同一個東西,改程式就等於重造機器。

突破在於儲存程式概念:把程式的指令存進原本就裝資料的同一塊可讀寫記憶體裡,並像其他數字一樣以數字編碼。如此一來,改程式就只是把不同的數字寫進記憶體——幾秒鐘,而非幾天。儲存程式概念正是讓同一台實體機器這一刻是文書處理器、下一刻變成西洋棋引擎的關鍵。硬體固定不變,記憶體裡的數字決定一切。

四個方塊的圖像:范紐曼模型

儲存程式電腦的標準草圖就是范紐曼模型:一個 CPU、一塊單一記憶體、一套面向外界的 I/O 系統,以及把它們連起來的匯流排——共用的線路。CPU 本身又分成兩半。控制單元是指揮:它決定接下來發生什麼,並送出引導一切的訊號。資料路徑則是樂團:暫存器、算術單元,以及真正搬運與運算數字的線路。

   +---------------------------- CPU ----------------------------+
   |                                                             |
   |   CONTROL UNIT  --- control signals --->  DATAPATH          |
   |   (decides what)                          (registers, ALU)  |
   |                                                             |
   +-------------------------------+-----------------------------+
                                   |
                          ====== B U S ======   <-- one shared road
                                   |
              +--------------------+--------------------+
              |                                         |
          +--------+                              +-----------+
          | MEMORY |  (instructions AND data)     |    I/O    |
          +--------+                              +-----------+
范紐曼模型:控制單元加資料路徑構成 CPU;一塊記憶體同時裝指令與資料;一切共用匯流排。

這張圖有一個安靜卻重要的後果。下一條指令和它需要的資料都來自同一塊記憶體、走同一條匯流排,一次一筆。這個唯一的共用門口——每條指令、每筆資料都得輪流擠過去——就是著名的范紐曼瓶頸。不管 CPU 想得多快,它能被餵食的速度終究受限於那一條路。坦白說,這條學習階梯接下來大半的內容,都是一場為了拓寬、繞過或藏起這個門口的漫長戰役。

哈佛架構,以及界線為何模糊

誠實的模型需要它的表親。哈佛架構把指令與資料放在兩塊獨立的記憶體、配兩條獨立的匯流排,於是 CPU 能在同一瞬間取一條指令、又讀一筆資料。它閃過了瓶頸——代價是較不靈活(程式較難把自己的程式碼當成資料看待)。這兩種設計常被畫成對手,但這種框架把現實簡化過頭了。

它實際如何運轉:指令週期

面對一塊裝滿指令數字的記憶體,機器如何前進?它重複一個叫做指令週期的小儀式,也就是「取指—解碼—執行」。一個特別的暫存器——程式計數器——存著下一條要跑的指令的位址。CPU 永遠在這幾個步驟上繞圈,而這個無止境的迴圈,就是一台電腦真正在做的全部。

  1. 取指:讀出程式計數器所指位址上的那條指令,把它從記憶體跨越匯流排拉進 CPU。
  2. 解碼:控制單元檢視這條指令的位元,弄清楚它的意思——是加法?從記憶體載入?跳躍?——並拉高對應的控制訊號。
  3. 執行:資料路徑動手做事——算術單元做加法,或算出位址後對記憶體讀寫。
  4. 前進:更新程式計數器(通常指向緊接的下一條指令,除非這條是把它改向的分支),然後繞回去取指。

這就是整台引擎。本階梯第四篇會把一條指令放大、走完這些階段;後面的階梯會揭露真正的 CPU 同時讓許多指令重疊進行,像一條洗衣流水線,這一批在洗、那一批在烘。但這個模型承諾的錯覺珍貴而且被守住了:結果看起來像是一次一條指令、按你寫下的順序發生,即使硬體私底下其實另有作為。

位元、字組、時脈——以及對「速度」的第一次誠實一瞥

上面的一切都以固定大小的塊在搬動。一個位元就是一個 0/1;八個位元組成一個位元組(byte);而字組是機器一次自然吞下的份量——你手機與筆電裡的 CPU 是 32 或 64 位元。暫存器、位址與算術單元的大小都以字組為單位,這就是為什麼你會聽到某台機器被叫做「64 位元」。同時,底下有一個穩定的時脈在滴答,每一下滴答——一個時脈週期——就是把指令週期往前推一格的心跳。

光憑時脈率來評斷一顆 CPU 很誘人——「這顆 4 GHz,一定比較快。」那就是百萬赫茲迷思,而它是錯的。誠實的算帳方式是效能鐵律:CPU 時間 = 指令數 x 每指令週期數(CPI)x 週期時間,其中 CPI 是平均每條指令的週期數,週期時間是時脈率的倒數。較高的時脈只縮短週期時間;一個吐出更多指令的草率編譯器,或一個 CPI 較差的設計,都能輕易吃掉那點好處。三個因子都重要,而且彼此互相拉扯。

幾十年來你可以無視這一切,因為時脈會自己一直往上爬。如今不再了。摩爾定律——晶片上電晶體數量大約每兩年翻一倍——仍蹣跚前行,但明顯在放緩。它殘酷的搭檔是 Dennard 微縮,這條規則說電晶體縮小時也按比例變得更涼、切換更省;它在 2005 年左右實質終結。一旦晶片無法再單純地跑更快而不熔毀,整個產業就硬生生轉向多核心與專用加速器。這個轉向——為什麼硬體不再自己加速——正是這條階梯後段幾乎所有內容存在的原因。