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

非揮發性與新興記憶體

DRAM 很快,卻很健忘——一拔電源,每個位元都不見了。本階最後一篇要認識那些「記得住」的記憶體:你 SSD 裡的快閃,以及那些新興的記憶單元(相變、MRAM),它們追逐著一個夢想的位置——快得像 DRAM,卻又像磁碟一樣持久。我們也會認識 ECC,它讓記憶體能熬過偶爾一次宇宙射線造成的位元翻轉,最後以一個誠實的判決收尾——通常設下天花板的,是記憶體,而不是核心。

揮發性就是健忘:DRAM 為何離不開牆上的插座

我們在這一階目前認識的所有東西,都藏著同一個缺陷。DRAM 把一個位元存成漏電電容裡的電荷,SRAM 把它存在電晶體的回授迴路裡——但兩者都是揮發性的(volatile):一切斷電源,電荷漏光、回授崩潰,那個值就乾乾淨淨地消失了。這正是為什麼你的電腦一開機就得從磁碟把一切重新載入,也是為什麼一份沒存檔的文件會死在一次停電裡。揮發性記憶體就像在鏡子上用水氣寫字;它寫得讀得都美妙地快,但只在你持續對它呵氣時才留得住。

非揮發性(non-volatile)記憶體則正相反:它在電源關閉後仍然守著自己的位元,守上好幾年,就像紙上的墨水。問題在於,讓一個記憶單元「不靠電源也記得住」的那套把戲,向來都得付出代價——速度、或寫入耐久度,或兩者兼具。幾十年來,這逼出了一道硬性的分界:一小撮揮發性、快速的工作記憶體(DRAM),緊挨著一大池非揮發性、緩慢的儲存(磁碟)。這正是你在快取那一階爬過的記憶體階層最底下那兩層,而本篇整個故事,就是關於什麼填進了——或可能終於填平了——它們之間那道延遲的鴻溝。

快閃:你早已擁有的非揮發性記憶體

你幾乎肯定早已擁有的非揮發性記憶體,是快閃(flash),每一顆 SSD、隨身碟和手機的心臟。一個快閃記憶單元是一個多了一招的電晶體:一個極小的浮閘(floating gate),一座被絕緣體圍起來的導體孤島。把一些電子推上那座孤島,它們即使斷了電源也會被困住——那團被困的電荷就是儲存的位元,而那道絕緣的牆,正是快閃為何非揮發性的原因。要讀取,晶片只需感測那團被困的電荷有沒有把電晶體的切換電壓移動。不論它坐在隨身碟裡還是資料中心的 SSD 裡,都是同一種浮閘記憶單元。

快閃有兩種彆扭的人格,形塑了建在它之上的一切。第一,它讀得快,卻寫得慢、抹除得更慢,而且你無法原地改寫單一個位元組——你必須先抹除一整個大區塊(block),才能把新資料寫進去。第二,每一次抹除都會極輕微地損傷那道絕緣牆,所以一個記憶單元在有限次數的寫入/抹除循環之後就會磨損報廢。現代的磁碟靠讀出好幾個不同的電荷位準,把 3 或 4 個位元塞進一個記憶單元,這密集得驚人,卻也更慢、更脆弱。這些怪癖,正是為什麼一顆 SSD 不能只是「帶持久性的 DRAM」;它需要一個聰明的管家。

那個管家就是快閃轉譯層(flash translation layer,FTL),SSD 內部一個把快閃怪癖對作業系統藏起來的小控制器。當作業系統覆寫一個邏輯區塊時,FTL 並不原地抹除;它把新資料寫到一個已經抹除好的新位置,再悄悄把位址重新映射,跟你在虛擬記憶體裡看過的位址轉譯一模一樣,只是換成了儲存。它靠把寫入平均地散佈到所有記憶單元上——磨損平衡(wear levelling)——阻止任何一個區塊提早死去。於是這顆磁碟「看起來」像一個單純、可重寫的區塊陣列;底下,FTL 卻一直在背景裡洗牌、重映射、抹除,只為了把那個假象維持住。

那個夢想的位置:儲存級與新興記憶體

快閃雖然非揮發性,卻太慢、太笨拙,無法「成為」主記憶體——你以大區塊(而非單一位元組)來定址它,而寫入慢如蝸行。於是階層裡留著一個誘人的空缺:一種儲存級記憶體(storage-class memory),像 RAM 一樣可以逐位元組定址、快得幾乎追上 DRAM,卻又像磁碟一樣持久而密集。填進那個位置,那道古老的、把「轉瞬即逝的記憶體」和「持久長存的儲存」分開的界線,就開始溶解。一整族的新興記憶體(emerging memory)技術正追逐著的,恰恰是這個夢想,每一種都把一個位元存進某種能熬過斷電、又沒有浮閘那種慢勁的物理狀態裡。

有三種值得點名。相變記憶體(phase-change memory,PCM)靠把一小撮玻璃狀材料熔成結晶態(低電阻)或非晶態(高電阻)來存一個位元——就像把水凍成清澈的冰或混濁的冰,再讀出你看見的是哪一種。MRAM 把一個位元存在一層奈米尺度薄膜的磁化方向裡,靠自旋極化電流來切換;它快、且耐受幾乎無限次的寫入,卻較難做得密集。ReRAM(電阻式 RAM)靠形成或切斷一條微觀的導電燈絲來翻轉電阻。這三種都是非揮發性、可逐位元組定址的,落在 DRAM 與快閃之間那道寬闊峽谷的某一處。

當一個位元自己翻了:ECC 與可靠性

記憶體並非完美可靠。一顆飛掠而過的宇宙射線中子,或一粒迷途的 α 粒子,能沉積剛好足夠的電荷,把單一個 DRAM 位元從 0 翻成 1——這是一次軟錯誤(soft error):資料錯了,但晶片本身毫髮無傷,下次仍會正確地儲存。在一台筆電上,這罕見到可以忽略;但一座擁有數百萬 GB 的資料中心,無時無刻不在見到這種翻轉,而一個在錯誤位置上悄悄損壞的位元,可能讓程式當掉,或更糟——悄無聲息地產出一個沒人察覺的錯誤答案。

防線是 ECC,錯誤更正碼記憶體(error-correcting code memory)。它的點子,就是你會用來守護一個電話號碼的那種冗餘:在每一塊資料旁邊多存幾個檢查位元,好讓硬體在每次讀取時都能重新算一遍、發現對不上。一種常見的方案叫 SECDED——單錯更正、雙錯偵測——它在每 64 個資料位元上加 8 個檢查位元,足以即時「精準找出並修正」任何單一個翻轉的位元,並「偵測」(雖不能修正)任意兩個。代價誠實而適度:大約多 12% 的記憶體晶片,和一絲絲延遲。

data word (no ECC):   [ 64 data bits ]  -> a flipped bit goes UNNOTICED

with SECDED ECC:      [ 64 data bits | 8 check bits ]
   on every read, hardware recomputes the 8 check bits:
     match            -> data is clean, pass it on
     1-bit mismatch   -> locate the bad bit, FLIP IT BACK, pass clean data
     2-bit mismatch   -> cannot fix, but REPORT the error (no silent corruption)

   cost: 72 bits stored per 64 useful bits  ~=  +12.5% memory
SECDED ECC 在每 64 位元的字上加 8 個檢查位元——足以即時修正任何單一位元翻轉,並偵測(並標記)雙位元翻轉,而不讓它悄悄溜過去。

留意這個點子的形狀,因為它在即將到來的可靠性那一階裡到處重現。你用一點點額外的硬體,換來可依賴性(dependability)——系統在故障存在時仍能正確運作,而不是當掉,或更糟,撒謊。ECC 把一個未被偵測到的靜默錯誤,變成一個被透明地修正、或被大聲回報的錯誤。它阻止不了那顆宇宙射線;它讓機器對「自己無法完美儲存什麼」這件事保持誠實。同樣這筆「用冗餘換信任」的交易,也撐起了跨磁碟的 RAID,以及信用卡號裡的檢查碼。

誠實的判決:天花板由記憶體決定

退一步,橫看這五篇導覽,有一個主題壓倒一切。我們認識了 SRAM 與 DRAM、列緩衝與更新、DDR 與通道與頻寬、HBM 與 3D 堆疊,現在又認識了非揮發性與新興的記憶單元。貫穿這一切,記憶體之牆巍然不動:處理器速度一路狂奔向前,記憶體延遲卻幾乎沒怎麼改善,所以一次 DRAM 存取,照樣讓 CPU 付出數百個空轉的週期。快取、預取、分庫、堆疊、聰明的控制器,都英勇地對抗著這道鴻溝——但它們是在「對抗」它,而非「抹除」它。對一大部分真實的程式而言,誠實的真相是:設下效能天花板的,是記憶體系統,而不是核心。

這把效能鐵律最後一次重新框定。執行時間 = 指令數 x CPI x 週期時間,而在受記憶體束縛的程式上,CPI 那一項由之主宰的不是算術,而是等待——耗在記憶體之牆上停頓的那些週期。這正是為什麼更快的時脈如此常令人失望(又是時脈迷思):你沒法靠拉高時脈,逃出一段由晶片另一頭的物理所設定的等待。地平線上最激進的修法,是乾脆別再搬資料了——記憶體內運算(processing in memory),讓簡單的運算就發生在記憶體陣列的內部或旁邊,從根上攻擊馮紐曼瓶頸,而不是把位元組在那一道窄門裡來回穿梭。

  1. 揮發性(DRAM、SRAM)一斷電就遺忘;非揮發性(快閃、PCM、MRAM)卻記得住好幾年——而換取那份持久的代價,向來是速度或耐久度。
  2. 快閃是非揮發性的,卻粗糙、寫得慢,所以 SSD 的快閃轉譯層靠重映射寫入並做磨損平衡,把它裝扮成一顆乾淨、可重寫的磁碟。
  3. 新興的儲存級記憶體追逐那個夢想位置——快如 DRAM 卻又持久——但必須在成本與密度上擊敗兩個被狠狠最佳化的在位者,這正是為什麼那個夢一再溜走。
  4. ECC 用約 12% 的額外晶片,換來修正單一位元翻轉、並標記雙位元翻轉;而貫穿這五篇,設下真正天花板的,是記憶體延遲,而不是核心。