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

記憶體之牆與 HBM

你現在懂了 DRAM 內部怎麼運作,也懂了 DDR、通道與位寬如何把頻寬一層層堆高。但有個前三篇一直暗示的麻煩:頻寬不斷攀升,延遲卻幾乎不動,而兩者都跟不上那顆嗷嗷待哺的處理器。這道鴻溝,就是記憶體之牆。這一篇老實地替它命名、指出它從何而來,並認識至今最大膽的一個答案——把記憶體往三維方向疊起來、貼到晶片身邊:HBM。

那道牆:怎麼都不肯降的延遲

想像一張涵蓋過去數十年的圖上有三條線。最上面那條,是處理器索取資料的速度,陡陡地往上爬。中間那條,是記憶體頻寬——每秒多少位元組——也在爬,慢一點,但還算體面,多虧了上一篇你認識的那些 DDR 世代、更多通道與更寬的匯流排。最下面那條,是記憶體延遲——單獨一次冷存取要花多久——卻幾乎沒動:十年前是幾十奈秒,今天還是幾十奈秒。最上面那條線與這條平坦底線之間越拉越大的鴻溝,就是記憶體之牆

延遲為什麼不肯降?因為它由一套頻寬把戲騙不過的物理所決定。開一條全新的 DRAM 列,照樣得來一次 ACTIVATE,把微弱的電荷倒上感測放大器、等它們穩定,再加上訊號在板子上跑個幾公分線路、來回到記憶體模組那不可避免的時間。你可以替高速公路加車道——那是頻寬——但你沒法讓任何一輛車更早抵達;速限和距離是固定的。DRAM 的延遲,就是那個速限和那段距離,而兩者都沒有像電晶體數目那樣進步過。

牆為什麼會痛:處理器在挨餓

牆對真實程式碼做了什麼,看這裡。假設你的處理器跑在大約 3 GHz,時脈週期約莫三分之一奈秒。一次一路打到 DRAM 的未命中,大概要 100 奈秒。除一下:這一次快取未命中量級上是約 300 個白白損失的週期——三百個週期裡,一顆超純量亂序執行的核心本可以退役幾百條指令,現在卻乾坐著,等一個數字送到。CPU 是個挨餓的天才;廚房很快,但食材在很遠的地方。

這就是為什麼一個快取的好處必須靠區域性去來,也是為什麼兩支結果一模一樣的程式,跑起來能差上好幾倍。對快取友善、以步幅掃過記憶體的程式碼,讓資料持續流動、把延遲藏起來;到處追指標、難以預測地亂跳的程式碼,則一再撞牆、停擺。記憶體之牆,正是區域性原則為何如此要緊的深層理由,是亂序核心為何在一次未命中還沒回來時,這麼拚命去找獨立工作可做的理由,也是預取器為何試著在你開口之前就把資料抓來的理由。它們全是對著同一道牆的藏延遲戰術。

頻寬、強度,與屋頂線

有個老實的辦法可以問:你的程式到底有沒有撞牆,而它歸結到一個比值。算術強度(arithmetic intensity)是你每從記憶體抓來一個位元組、所做的有用運算次數。如果你讀一個位元組、對它做一百次浮點運算,你就是受計算限制——處理器是瓶頸,記憶體輕鬆跟上。如果你讀一個位元組、只做一次便宜的加法,你就是受記憶體限制——你在挨餓,被頻寬卡住,不管核心多快都一樣。

Performance (ops/sec)
  ^
  |            ____________  <- compute roof (peak ops/sec)
  |           /
  |          /  <- the slope IS memory bandwidth
  |         /
  |        /
  |_______/________________________> arithmetic intensity (ops per byte)
          ^                     ^
     low intensity:        high intensity:
     MEMORY-BOUND          COMPUTE-BOUND
     (hits the wall)       (memory keeps up)
屋頂線模型:在低算術強度時,你被釘在那道傾斜的頻寬屋頂之下(記憶體之牆);只有越過那個轉角,純算力才成為限制。

這幅小圖就是屋頂線模型,它把那道牆變得具體:屋頂那段斜的部分,就是記憶體頻寬,而任何算術強度低的程式,都被釘在它底下,不管你丟多少核心進去,都搆不到那片平坦的計算天花板。這個教訓令人謙卑,也值得直白地說出來:對一大片真實工作負載而言,瓶頸根本不是處理器。是記憶體設下了天花板——這正是整級階梯一再回到的那個誠實註腳。

HBM:把記憶體往上蓋、把它搬得更近

如果你沒法讓單一次 DRAM 存取更快,那麼次好的一招,就是一口氣做極多次,並縮短位元組要走的距離。這正是 高頻寬記憶體(HBM)做的事。HBM 不把幾顆 DRAM 晶片平攤在主機板上,而是拿一小疊 DRAM 晶粒、一片片往上堆——三維堆疊——用垂直的線直接鑽穿矽(矽穿孔,through-silicon vias)把各層連起來。這疊東西接著就坐在跟處理器同一個封裝上,只隔幾毫米,落在一塊叫作中介層(interposer)的微小共用底座上,而不是隔著板子上的幾公分。

兩個好處隨之而來,而值得把哪個是哪個說清楚。第一,因為記憶體就在封裝上,你可以拉一條寬到驚人的匯流排接它——一千條線甚至更多,而一般 DRAM 的一個通道只有 64 條。回想上一篇那條公式,頻寬 = 位寬 x 速率 x 通道數:HBM 把位寬衝破天花板,於是它的總頻寬是傳統 DRAM 的好幾倍。第二,這段短距離與貼近的控制器,省下一點延遲、以及每位元組大量的能量,因為把位元推個幾毫米,遠比推過一整塊板子便宜。

與牆共處,順道談談 ECC

因為這道牆拆不掉,整個領域學會了與它共處,而你已經認識了每一種戰術。我們用多層快取預取把延遲藏起來。我們用亂序執行、以及在一次未命中飛行途中切去做別的事的執行緒去容忍它。我們用記憶庫平行、通道與 HBM 去榨取頻寬。我們也越來越常把運算搬向資料——記憶體內運算(processing-in-memory)與近資料運算這些最後一篇會碰到的點子——因為最便宜的那個位元組,是你根本不必搬動的那一個。

還有一件事,隨著這一切密度一起搭便車:錯誤。把幾十億個微小電荷塞進一顆晶片,總會有位元自己翻掉——一道宇宙射線、電氣雜訊,或上一篇那個 Rowhammer 擾動。防線是錯誤更正碼(ECC)記憶體:在資料旁邊多存一些位元,讓控制器在每次存取時都能偵測、通常還能更正一個翻掉的位元。伺服器與 HBM 等級的系統把 ECC 當作不可妥協,因為在規模之下,一個「十億分之一」的翻轉每天會發生好多次。它花掉一點容量、一點頻寬——一筆換來你真能信任的記憶體的誠實稅。

所以這裡是帶往下一步的誠實總結。記憶體頻寬不斷攀升,HBM 攀得叫人嘆為觀止,但單一次冷存取的延遲二十年來原地踏步——而對極多程式來說,設下天花板的,正是那個卡住不動的數字,而非處理器。本級階梯下一篇、也是最後一篇,會把目光越過今天的 DRAM:快閃、相變化與 MRAM——那些不靠電源就能握住位元、總有一天也許會把記憶體與儲存之間那條線徹底模糊掉的非揮發性與新興記憶體。