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

SRAM 對 DRAM:速度、密度、成本

快取那一級一直把一種記憶體叫作又快又小、另一種叫作又大又慢。現在我們掀開蓋子,認識這兩種元件本身——SRAM 與 DRAM——看清為什麼一個是用六顆電晶體換來的速度,另一個是用一顆電晶體換來的便宜,便宜到必須在它遺忘之前刷新它。

記住一個位元的兩種辦法

整個快取那一級,我們都靠著一個方便的速記:SRAM是快取用來蓋成的又快又小之物,DRAM則是底下又大又慢的主記憶體。這是真的,但它是個標籤,不是個解釋。這一級要掀開晶片本身。它們之間整個分裂,歸結到向晶片上每一顆電晶體問的一個問題:我們願意花多少顆電晶體去記住一個位元 答「六顆」,你得到速度。答「一顆」,你得到便宜。其餘的一切——價格、密度、刷新、記憶體之牆——全都從這一個選擇流淌出來。

SRAM——靜態隨機存取記憶體——把每個位元存在一個由兩個反相器組成的小迴圈裡,它們互相握住對方的狀態,鎖死在兩個穩定位置之一。這跟暫存器檔用的是同一個雙穩態把戲,這也正是為什麼暫存器檔與 L1 快取都是用它做的。因為這個迴圈主動握住自己,只要通著電,位元就待著不動,毋須維護——這就是它名字裡那個「靜態」。代價是體積:一個經典 SRAM 單元要用六顆電晶體,所以每存一個位元,你都在替六個開關以及把它們連起來的導線付錢。

DRAM——動態隨機存取記憶體——不肯花六顆電晶體。它把每個位元存成一顆微小電容上的電荷,由單獨一顆存取電晶體看守:有電荷代表 1,空了代表 0。每個位元一顆電晶體加一顆電容。在單元層級上這大約比 SRAM 密六倍,這就是為什麼你機器裡有好幾 GB 的 DRAM,快取卻只有幾 MB 的全部原因。但電容是一只會漏的水桶——電荷會在幾毫秒內流光——所以 DRAM 是「動態」的:放著不管,它就遺忘。下一節我們就要替這個漏洞付帳。

那個漏洞,以及記得的代價

因為 DRAM 電容會漏,晶片必須週期性地讀出每一列再把電荷寫回去,趁它跌破那條把 1 和 0 分開的門檻之前,把它補滿。這個雜務叫刷新,它自動發生,典型上整個陣列每 64 毫秒一輪。刷新是 DRAM 為它的密度付的稅:它花掉一點能量,而且偶爾某一列正忙著被刷新時,恰好就是處理器想用它的時候,於是多出一個小停頓。SRAM 不欠這種稅——它的位元自己握住自己——這就是 SRAM 為什麼比較快(而不只是比較小)的一半原因。

SRAM 反應更快,還有一個比「不欠刷新」更深的原因。SRAM 單元主動驅動它的輸出——反相器迴圈用力推著位元線,於是一次讀取又快又有把握。DRAM 的讀取則是一場細膩的測量:打開存取電晶體,讓那一丁點儲存的電荷把一條大得多的位元線輕輕撥動一絲,再由一個感測放大器去偵測並重建它。那番感測要花時間,而且——因為讀取會把電容放掉——每一次 DRAM 讀取都必須立刻把值寫回去。SRAM 是把它的位元喊出來;DRAM 則得有人小心地去聽。

速度、密度、成本——三個互相打架的數字

現在把兩者並排,這個取捨就十分鮮明。SRAM 在延遲上以很大的差距勝出——在快取裡是幾百皮秒到一兩奈秒,碰到一個 DRAM 單元卻要幾十奈秒。DRAM 在密度、從而在每位元成本上勝出,同樣差距很大,因為一顆電晶體贏過六顆。你真的無法兩者兼得:讓 SRAM 快的那個東西(一個主動的六電晶體單元),正是讓它又大又貴的東西;而讓 DRAM 便宜的那個東西(一個單電晶體的電荷單元),正是讓它又慢又健忘的東西。

                 SRAM                      DRAM
  ------------   -----------------------   -----------------------
  cell          ~6 transistors            1 transistor + 1 capacitor
  density       low  (big cell)           high (~6x denser)
  cost / bit    high                      low
  latency       very fast (<1-few ns)     slow (tens of ns to a cell)
  refresh?      no  (static, self-held)   yes (dynamic, leaks)
  volatile?     yes                       yes
  used for      register file, L1/L2/L3   main memory (the DIMMs)

  Same job (hold a bit) -- opposite engineering bargain.
  Six switches buy speed; one transistor buys cheapness.
SRAM 對 DRAM 一覽。確切時序依製程與設計而異;普世不變的,是那筆交易的形狀——又快又貴對上又密又便宜。

這正是快取階層之所以存在的全部原因,而你剛學到的這些元件事實,就是它的地基。我們絕不可能用 SRAM 蓋出主記憶體——好幾 GB 的六電晶體單元會大得不可能、貴得要命。我們也絕不可能用 DRAM 蓋出快取又保持它快。所以架構師兩者都用:緊貼管線的一層薄薄 SRAM 換速度,它後面一片深深的 DRAM 海洋換容量,再用上一級那個區域性把戲,讓那片慢海洋多數時候感覺起來很快。SRAM 對 DRAM 不是一場有贏家的競賽;它是階層之所以分層的原因。

一步步讀出一個 DRAM 單元

值得把一次 DRAM 讀取慢慢走一遍,因為這一級其餘的部分都建立在這些動作上。單元坐在一格列與行的網格裡;要讀一個位元,你不是直接把它摘下來,而是先把它整列拉上一條感測放大器帶,再從那條帶上挑出你要的行。這個「先網格、再帶條」的舞步,正是為什麼 DRAM 有著下一篇導覽要細看的列與行時序。

  1. 開列(活化)。控制器選定一列;該列每顆電容的存取電晶體都把自己接上位元線,輕輕地把它們往上或往下推。
  2. 感測並鎖存。感測放大器偵測那些微小的推動,把每一個放大成完整的 0 或 1,並把整列握在一個晶片內的快速緩衝區裡(也就是列緩衝)。
  3. 讀出行。從那已鎖存的列裡,控制器選出它真正想要的行,把那些位元送出去。從同一個已開的列再讀更多行,現在很便宜——這一列已經升起來了。
  4. 寫回並關閉(預充電)。因為感測把電容放掉了,放大器把電荷復原,接著位元線被重置,好讓下一次能開另一列。

注意第 3 步裡藏著的那個不對稱。開一列是昂貴的部分;一旦它坐進了列緩衝,同一列的更多位元就幾乎免費而來。這一個事實——列一開,相鄰位元就便宜——正是空間區域性之所以划算的元件層級根源,也是為什麼當你照順序串流穿過記憶體、而不是到處亂跳時,記憶體跑得最快。快取那一級告訴你區域性很重要;這就是獎賞它的那部實體機器。

為什麼記憶體元件設下了上限

這裡是這整級誠實、略帶洩氣的標題:很多時候,設下效能上限的是記憶體元件,不是處理器。DRAM 晶片裡的一顆電容,受制於一套在邏輯不斷變快的同時幾乎沒怎麼進步的物理——這正是快取那一級的記憶體之牆,現在從元件那一側看過去。你可以買一顆核心數加倍、或時脈率更高的 CPU,但若你的程式在等 DRAM,那些多出來的核心就一輩子卡著空轉。這就是為什麼這麼多真實世界的效能工作,講的是尊重記憶體,而不是把它的時脈比過去。

在我們繼續往上爬之前,給兩個誠實的但書。第一,密度買不到速度:一個更密、更便宜的 DRAM 世代給你更多容量、往往也更多頻寬,但碰到一個新列的延遲,數十年來幾乎沒挪動過——容量與延遲是不同的軸,把它們混為一談是個經典錯誤。第二,這兩種記憶體都不完美。一道宇宙射線或一顆迷途粒子能翻轉一個儲存的位元——一個軟錯誤——在一台有著海量 DRAM 的機器裡,這很罕見但確實存在。伺服器靠 ECC 記憶體來防它,它多存一些檢查位元,好讓單位元翻轉被抓到並改正,用一點容量換來可信賴的資料。