跳轉到

第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 沒有移位、乘法與除法的電路,以及浮點數,運算數度會變慢

乘法變通方式:通過自己加上自己,然後針對對應的位置移位後相加,這樣計算方式非常迅速

設計單精雙精浮點數運算

乘法

加法

單精、雙精作家法時,會需要做等值的計算

做加法時,要跟大的對齊,避免高位元數值遺失

將數字較小的與大的對齊。

所以勒

1.00011×106+1.01010×1061.01110×106 \begin{smallmatrix} & 1.00011 \times 10^6 \\ + & 1.01010 \times 10^6 \\ \hline & 1.01110 \times 10^6 \end{smallmatrix}

如果跟小的位元對及,會損失高位元數值示:

除法

參考課本的內容

改為前瞻加法器

使用前瞻進位加法器

現代處理器加速

  • 多層次快取
  • 管線
  • 平行 + 虛擬化
  • 交給專用計算硬體加速

前提

以不增加快取的前提下達成

分層快取

  1. 暫存器
  2. 快取 SRAM 1. L1 2. L2 3. L3 4. L4
  3. 主記憶體 DRAM
  4. 磁碟

快取很重要

適時的增加快取可以增加速度

不用快取

如果沒有快取,會像記憶體速度看齊,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 深度學習 挖礦等

張量處理器 高維、向量運算