第6章 計算機組織與設計
簡介¶
在設計一顆處理中,我們可以透過很多很多 NAND 就可以設計出一台電腦,一個好的 CPU 除了硬體上要設計到最好,還要搭配整體的架構去發揮與運用。
除了硬體內部功能的架構,也要依照時脈設計剛好指令集使用,才可以讓指令集在一個時間內使用,才不會浪費時間在等待下一個指令的時間,這部份會在這章節結尾時分別概述如何設計一顆快速的 CPU 。
處理器架構¶
處理器中有兩種架構最為知名與常見,分別為馮紐曼架構與哈佛架構,這兩種也常常會對應著複雜指令集與精簡指令集。
馮紐曼架構¶
馮紐曼架構
複雜指令集
指令存在記憶體,資料也存在記憶體
哈佛架構¶
哈佛架構
精簡指令集
指令有專門的記憶體,資料是另外處理。
很適合嵌入式系統可以運作,因為指令儲存單元已經寫好了。
現在處理器架構¶
在現在的處理器中,除了單晶片等較為簡單需求的處理架構,基本上都會混用架構,尤其大家常說的 Intel 複雜指令集架構,但如果仔細往裡面推敲的話,會發現…ㄟ!怎麼有哈佛架構的身影~
由此可以知道 Intel 為了要維持過往處理器的相容,再大架構上會保持不便,但為了跟不上市場的需求與變化,因此會將內部混用哈佛。
遠看馮紐曼架構,近看哈佛架構
指令集架構¶
現在常見的指令集架構有 MIPS 、 x86 、 ARM 、 RISV-V 架構。
範例¶
MIPS CPU¶
Nand2Tetris¶
真值表
| time | in | reset | load | inc | out | | ---- | ------ | ----- | ---- | --- | ------ | | 0+ | 0 | 0 | 0 | 0 | 0 | | 1 | 0 | 0 | 0 | 0 | 0 | | 1+ | 0 | 0 | 0 | 1 | 0 | | 2 | 0 | 0 | 0 | 1 | 1 | | 2+ | -32123 | 0 | 0 | 1 | 1 | | 3 | -32123 | 0 | 0 | 1 | 2 | | 3+ | -32123 | 0 | 1 | 1 | 2 | | 4 | -32123 | 0 | 1 | 1 | -32123 | | 4+ | -32123 | 0 | 0 | 1 | -32123 | | 5 | -32123 | 0 | 0 | 1 | -32122 | | 5+ | -32123 | 0 | 0 | 1 | -32122 | | 6 | -32123 | 0 | 0 | 1 | -32121 | | 6+ | 12345 | 0 | 1 | 0 | -32121 | | 7 | 12345 | 0 | 1 | 0 | 12345 | | 7+ | 12345 | 1 | 1 | 0 | 12345 | | 8 | 12345 | 1 | 1 | 0 | 0 | | 8+ | 12345 | 0 | 1 | 1 | 0 | | 9 | 12345 | 0 | 1 | 1 | 12345 | | 9+ | 12345 | 1 | 1 | 1 | 12345 | | 10 | 12345 | 1 | 1 | 1 | 0 | | 10+ | 12345 | 0 | 0 | 1 | 0 | | 11 | 12345 | 0 | 0 | 1 | 1 | | 11+ | 12345 | 1 | 0 | 1 | 1 | | 12 | 12345 | 1 | 0 | 1 | 0 | | 12+ | 0 | 0 | 1 | 1 | 0 | | 13 | 0 | 0 | 1 | 1 | 0 | | 13+ | 0 | 0 | 0 | 1 | 0 | | 14 | 0 | 0 | 0 | 1 | 1 | | 14+ | 22222 | 1 | 0 | 0 | 1 | | 15 | 22222 | 1 | 0 | 0 | 0 |Verilog程式碼
Verilog測試檔案
HDL 程式碼
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/03/a/PC.hdl
/**
* A 16-bit counter with load and reset control bits.
* if (reset[t] == 1) out[t+1] = 0
* else if (load[t] == 1) out[t+1] = in[t]
* else if (inc[t] == 1) out[t+1] = out[t] + 1 (integer addition)
* else out[t+1] = out[t]
*/
CHIP PC {
IN in[16],load,inc,reset;
OUT out[16];
PARTS:
// Put your code here:
Inc16(in=in, out=inc16);
Mux16(a=inc16, b[0..15]=false, sel=reset, out=muxReset);
Mux16(a=muxReset, b=in, sel=load, out=muxLoad);
Mux16(a=out, b=inc16, sel=inc, out=muxInc);
Register(in=muxInc, load=, out=out);
}
計算機暫存器¶
一個 CPU 會由許多的暫存器所組成,給予 ALU 在資料運算上還有資料可以儲存。
下列會有馮紐曼架構的暫存器結構。
記憶體¶
由暫存器、多工器、解多工器組成的大型陣列暫存器,並且因為多工器與解多工器提供了定址的功能,在第二部曲有稍微講解記憶體架構與組成,在第三部曲有專門講解由記憶體組成的可程式規劃裝置,詳細描述記憶體組成方式。
資料暫存器¶
「資料暫存器」(DR, Data Register)保存記憶體運算元。
位址暫存器¶
保存記憶位址。
累積器¶
處理暫存器
指令暫存器¶
暫時將指令儲存的暫存器,這類的架構為馮紐曼架構,指令與資料是分開的。
程式計數器¶
當指令從 CPU 的輸入進入時,經過「解碼單元」與「控制單元」後轉移,會將指令儲存到「指令暫存器」,對應的位置會儲存在「程式記數器」。
也就是說當 CPU 在執行程式的時候,會依照計數器對應給定的未去找到指令,依照指令循序的執行,此指令會去對記憶體中的資料動作時,會透過輸入指令位置。
程式計數器¶
臨時暫存器¶
輸入暫存器¶
輸出暫存器¶
如何加速?¶
DFF 有一種隔絕資料的一種效果,現在的管線設計會通過DFF把不同狀態隔絕
n2t的記憶體作法是很貴的作法,通常通是在一級快取的方式
因此通常會專門的DRAM方式來做,比較便宜,雖然比較慢
最不容易設計的是PC,程式計數器
設計方式,要先有組合語言,三張表格,是指令集功能
記憶體映射輸入輸出
多核心、快取、管線
n2t的記憶體會很貴
使用記憶體會變慢,但省成本
處理器的處理速度是電腦科學領域中一直追求的內容,通過不同的作法可以達到加速,不管是透過硬體設計、結構、指令集等方式,都是可以讓電腦速度加速的方式。
使用加法快速計算:
n2t 沒有移位、乘法與除法的電路,以及浮點數,運算數度會變慢
乘法變通方式:通過自己加上自己,然後針對對應的位置移位後相加,這樣計算方式非常迅速
設計單精雙精浮點數運算¶
乘法¶
加法¶
單精、雙精作家法時,會需要做等值的計算
做加法時,要跟大的對齊,避免高位元數值遺失
將數字較小的與大的對齊。
所以勒
如果跟小的位元對及,會損失高位元數值示:
除法¶
參考課本的內容
改為前瞻加法器¶
使用前瞻進位加法器
現代處理器加速¶
- 多層次快取
- 管線
- 平行 + 虛擬化
- 交給專用計算硬體加速
前提¶
以不增加快取的前提下達成
分層快取¶
- 暫存器
- 快取 SRAM 1. L1 2. L2 3. L3 4. L4
- 主記憶體 DRAM
- 磁碟
快取很重要¶
適時的增加快取可以增加速度
不用快取¶
如果沒有快取,會像記憶體速度看齊,n2t沒有暫存器
存取不到快取資料¶
C語言無法存取到快取資料
因此如果將資料跳躍存取會讓快取無法得到快取的幫助,會需要堆疊的方式
區域性策略要好¶
好的區域性策略如下
int a[10000][10000];
for (size_t i = 0; i < 10000; i++) {
for (size_t j = 0; j < 10000; j++) {
printf("%d\n", a[i][j]);
}
}
不好的區域性策略如下
int a[10000][10000];
for (size_t i = 0; i < 10000; i++) {
for (size_t j = 0; j < 10000; j++) {
printf("%d\n", a[j][i]);
}
}
原因是陣列是循序分配記憶體,一個一個接著紀錄著,因此如果非循序結構的話會讓記憶體無法將資料儲存到快取內。可以看到內容
img_3092
快取¶
透過加入更大的快取來增加運算的速度,減少馮紐曼瓶頸的狀況。
平行¶
三種平行機制
- 管線
- 多核心 + 虛擬化
- 專用處理器
管線¶
何謂管線¶
過去的作法是將資料儲存回記憶體,然後在讀取回來處理,現在的作法是設計許多的暫存器,提供暫存後在拿回來處理。
所謂的管線就是透過暫存器連結不同單元與微運算之間,也透過管線方式讓各個區域分離,讓各個區域之間可以獨立運作但又可以互相連結,相對過去單一的匯流排會比較迅速
因此指令集設計會直接影響到效能,設計時要計算每個CPU的指令時間,以得到最佳時脈,透過這個方法可以讓資料以及計算在匯流排可以滿載。
MIPS CPU
管線缺點¶
- 被跳躍指令打斷,做已經完成的事情都會拋棄
- 管線氣泡:如果資料沒有在暫存器,那這樣記憶體沒有資料就必須等待資料進來
因此暫存器不能太多,太多會讓資料流向錯誤的地方,或者需要等待才可以將資料導向需要的地方。
多核心¶
透過內含不同的核心去運算。
多核心問題¶
thread 執行緒 問題
超執行緒¶
一個CPU會提供兩個邏輯執行緒
利用閒置情形利用這個時間利用與運算
例如將ALU拉出來,給其他人使用,專門給一個暫存器給邏輯執行緒
這部份各覺得是在控制單元部份就要寫好
控制單元也會包含了其他運用
專門處理器¶
通過內含多個ALU來分擔同時運算,來加速需要同時運算性質的計算。
以 CPU + GPU 合作
特殊領域¶
AI 深度學習 挖礦等
張量處理器 高維、向量運算