National Central University
Uedu Main Site
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try an AI Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

3

Local AI

--

Uedu Code

--

中央大學 AQI 80 24°C PM2.5 21
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 12

記憶體階層與快取

暫存器、快取、主記憶體、硬碟:越快越小越貴
Interaction 25 minute(s)

Learning Objectives

  • 說出記憶體階層各層(暫存器、快取、主記憶體、儲存裝置)在速度、容量與成本上的取捨
  • 說明快取命中、未命中與命中率,並估算平均存取時間
  • 比較直接對映、集合關聯與全關聯快取,判斷一串存取的命中與未命中
  • 用時間區域性與空間區域性解釋為什麼快取有效,以及走訪陣列的順序為什麼會影響速度

這一課要回答的問題

CPU 每秒可以做數十億次運算,但它要的資料放在記憶體裡。如果每做一次加法都要等主記憶體送資料過來, CPU 大部分時間都在空等。

你可能也有這些經驗:

  • 同一個程式,第二次打開比第一次快
  • 同樣是處理一張大表格,換一種走訪順序,速度差好幾倍
  • 規格表上寫著「L2 快取」「L3 快取」,卻不知道它們是做什麼的

這一課要回答:電腦怎麼讓「又快又大」的記憶體看起來存在? 答案是記憶體階層(memory hierarchy)與快取(cache)。

記憶體階層:越快的越小、越貴

沒有一種記憶體同時又快、又大、又便宜,所以電腦把幾種記憶體疊成一層一層:

層級 在哪裡 用什麼做 容量(大約的數量級,示意) 存取時間(大約的數量級,示意)
暫存器(register) CPU 裡面 正反器 幾十到幾百個,每個 64 位元 不到 1 奈秒
L1、L2、L3 快取 CPU 晶片上 SRAM 幾十 KB 到幾十 MB 約 1 到數十奈秒
主記憶體 主機板上的記憶體模組 DRAM 數 GB 到數十 GB 約數十到一百奈秒
固態硬碟(SSD) 儲存裝置 快閃記憶體 數百 GB 到數 TB 約數十到數百微秒
傳統硬碟(HDD) 儲存裝置 磁性碟片 數 TB 約數毫秒

1 毫秒=1000 微秒=1,000,000 奈秒。從快取到硬碟,速度差了大約一百萬倍。

往下走的規律:速度越慢、容量越大、每個位元組越便宜。 另外,暫存器、快取與主記憶體是揮發性(volatile)的,斷電資料就消失;SSD 與硬碟是非揮發性的,關機後資料還在。

比喻:你寫報告時,正在看的那一頁攤在桌上(暫存器),常用的幾本書放在手邊的書架(快取), 整個房間的書櫃放得更多但要起身去拿(主記憶體),找不到的再去圖書館借(硬碟)。 大部分時候你只需要桌上和書架上的東西,所以感覺很快。

SRAM 與 DRAM:SRAM 每個位元用好幾個電晶體保存,速度快、不需要更新,但佔面積、成本高,所以只做成容量小的快取; DRAM 每個位元只用一個電晶體加一個電容,密度高、便宜,但電容會漏電,必須定期「更新」(refresh),速度也比較慢,適合做容量大的主記憶體。

想一想:記憶體階層

1.

關於記憶體階層,下面哪一個敘述正確?

2.

突然停電再開機,下面哪一層原本的資料還在?

第 1 次作答

快取:先找手邊的

快取(cache)是放在 CPU 與主記憶體之間、容量小但很快的記憶體,存放「最近用過」的資料副本。CPU 要讀一個位址時:

  1. 先查快取。找到了叫命中(hit),很快就拿到。
  2. 找不到叫未命中(miss),要到主記憶體去拿,比較慢;拿回來時順便放一份進快取,下次就可能命中。
  3. 快取滿了,就要選一個舊的資料取代(replace)掉。

衡量快取好不好,看命中率:

命中率 = 命中次數 ÷ 存取次數
平均存取時間 = 命中時間 + 未命中率 × 未命中懲罰

假設命中只要 1 個時間單位、未命中要多花 100 個時間單位(示意值):命中率 90% 時平均是 1 + 0.1 × 100 = 11;命中率 99% 時平均是 1 + 0.01 × 100 = 2。 命中率看起來只差 9%,平均速度卻差了 5 倍以上,所以快取的設計很在意命中率。

快取怎麼知道某一格放的是哪個位址?每一格除了資料,還記著一個標籤(tag),用來比對「這格放的是不是我要的那個」。 下面的程式模擬最簡單的一種快取:4 格,每個位址只能放在固定的一格。

逐步執行:直接對映快取的命中與未命中

串列 cache 代表快取的 4 格,'空' 表示這格還沒放東西。每個位址只能放在「位址除以 4 的餘數」那一格。注意位址 0 和 4 的餘數都是 0:它們會搶同一格。

三種對映方式

「一個位址可以放在快取的哪幾格」,叫做對映方式(mapping):

對映方式 規則 找資料時要比對幾格 缺點
直接對映(direct mapped) 每個位址只能放在固定的一格(位址 ÷ 格數的餘數) 1 格,最簡單、最快 兩個位址搶同一格時,會一直互相趕走
集合關聯(set associative) 快取分成好幾組,每組有 2、4、8…格;位址決定放哪一組,組內任選一格 組內那幾格 介於兩者之間
全關聯(fully associative) 任何位址可以放在任何一格 全部的格子 每次都要同時比對全部格子的標籤,硬體貴、耗電

格子都滿了要取代誰?常見的做法是 LRU(Least Recently Used):取代最久沒用到的那一格,因為最近用過的很可能馬上又會用到。

真實的 CPU 快取多半是集合關聯(例如每組 8 格或 16 格):比直接對映少很多衝突,又不像全關聯那麼耗費硬體。

互動練習:比較三種對映方式

左邊是 16 個字組的主記憶體,格子底下的色條表示這個位址會放到快取的哪一格(或哪一組);右邊是 4 格的快取。先選對映方式與存取序列,再按「單步存取」一個一個看,或按「全部執行」。上方的說明會算給你看:位址除以幾、餘數多少、放哪裡、有沒有命中。照下方任務做:先用直接對映跑「0 4 0 4 0 4」並回答為什麼 0 和 4 互相取代,再換成 2 路集合關聯比較命中率;接著跑「0 4 8 0 4 8」,找出能讓命中率達到 50% 的對映方式,最後回答真實 CPU 為什麼不全部用全關聯。你也可以在輸入框打自己的序列(位址 0~15,用空白隔開)。

算一算:命中幾次

1.

直接對映、4 格的快取,一開始是空的,依序存取位址 2 6 2 6,一共命中幾次?

2.

2 路集合關聯、共 4 格(2 組,每組 2 格),未命中時取代組內最久沒用到的(LRU)。一開始是空的,依序存取 1 3 1 3 5 1,一共命中幾次?

3.

命中時間 1 個單位、未命中懲罰 100 個單位、命中率 90%,平均存取時間大約是幾個單位?

第 1 次作答

區域性:快取為什麼有效

快取只有主記憶體的一小部分,卻常常有很高的命中率,因為程式存取資料有規律,叫做區域性(locality):

  • 時間區域性(temporal locality):剛用過的資料,很快會再用到。例如迴圈裡每一圈都會讀寫的累加變數、迴圈本身的指令。
  • 空間區域性(spatial locality):用到一個位址,附近的位址很快也會用到。例如依序讀陣列的元素、依序執行的指令。

為了利用空間區域性,快取每次從主記憶體搬的不是一個字組,而是一整個區塊(block,也叫快取線 cache line), 包含相鄰的好幾個字組。讀第一個元素時未命中,但同一個區塊裡的下幾個元素就都命中了。

陣列的走訪順序會影響速度。 二維陣列在記憶體裡通常是逐列存放:先放 a[0][0] a[0][1] a[0][2] a[0][3],再放 a[1][0]…。

# 逐列走訪:依序讀相鄰的位址,空間區域性好
for i in range(4):
    for j in range(4):
        total = total + a[i][j]

# 逐行走訪:每次跳一整列,快取小時,載入的區塊還沒用完就被趕走
for j in range(4):
    for i in range(4):
        total = total + a[i][j]

兩段程式算出的結果一樣,存取次數也一樣,但命中率可以差很多。下面的模擬器用一個 4 × 4 的陣列和只有 2 格的快取,讓你親眼看到差別。

互動練習:走訪順序與區塊大小

左邊把 16 個字組畫成 4 × 4 的陣列 a(每一列 4 個元素,逐列存放),綠底表示目前在快取裡。快取是直接對映、只有 2 格,區塊大小 4 個字組時,每格剛好放陣列的一整列。依任務先跑「逐列走訪」,再跑「逐行走訪」,比較命中率並回答原因;接著把區塊大小改成 1,再跑一次逐列走訪,看看「一次搬一整個區塊」對空間區域性有多重要;最後判斷哪一種情況是時間區域性。

想一想:區域性

1.

二維陣列 a 在記憶體中逐列存放(a[0][0]、a[0][1]… 相鄰)。要把每個元素加總,哪一種迴圈通常比較快?

2.

同一個程式第二次打開通常比第一次快,最主要是利用了什麼?

第 1 次作答

重點整理

  • 記憶體階層:暫存器 → 快取(SRAM)→ 主記憶體(DRAM)→ SSD → 硬碟;越往下越慢、越大、每個位元組越便宜。前三層斷電就消失,儲存裝置不會。
  • 快取存放最近用過的資料副本;找到叫命中,找不到叫未命中,要到下一層拿並放一份進快取。
  • 平均存取時間=命中時間+未命中率 × 未命中懲罰;命中率差一點,平均速度就差很多。
  • 對映方式:直接對映(每個位址固定一格,簡單但容易衝突)、集合關聯(組內任選)、全關聯(任一格,硬體最貴);滿了常用 LRU 取代最久沒用的。
  • 時間區域性(剛用過的很快再用)與空間區域性(附近的很快會用到)讓小小的快取也有高命中率;快取以區塊為單位搬資料,所以走訪陣列要順著存放的順序。

下一課:記憶體階層的最底層,儲存裝置。硬碟與 SSD 的運作原理為什麼讓它們速度差這麼多,CPU 又怎麼和這些輸入輸出裝置溝通。

這一課完成了!
Next lesson:儲存裝置與輸入輸出
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。