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

屋頂線模型:浮點運算都跑哪去了?

在你最佳化任何東西之前,先學會診斷一段核心函式是缺運算還是缺資料搬運——這是機器學習系統最有用的一項技能。

系統工程師問的第一個問題

你對一個訓練步驟做效能剖析(profile),發現 GPU 使用率只有 30%。直覺是再加更多運算。這個直覺通常是錯的。現代加速器每秒能做的算術,遠多於它從記憶體讀取資料的能力,所以多數真實核心函式的一生都在等待資料,而不是等待運算。屋頂線(roofline)框架給你一句話的診斷:這段核心函式是受限於運算,還是受限於記憶體頻寬(memory bandwidth)?你接下來做的每件事都取決於這個答案。

算術強度:每位元組的浮點運算

算術強度(arithmetic intensity)是有用的浮點運算數,與運算單元和記憶體之間搬移的位元組數的比值。它是演算法與其資料布局的性質,而非硬體的性質。兩個 N×N 矩陣的大型矩陣乘法約做 2N³ 次浮點運算,卻只搬約 3N² 個浮點數,所以強度隨 N 增長——這就是為什麼大型 GEMM 是 GPU 上最友善的工作負載。相對地,逐元素的激發函數讀一個值、做一次乘法、再寫回:強度接近 1。

\text{Arithmetic Intensity} \;=\; \dfrac{\text{FLOPs}}{\text{Bytes moved}}

算术强度:有用的浮点运算量除以在计算单元与内存之间搬运的字节数。

intensity = useful_flops / bytes_moved
# N=4096 matmul:  ~2.7e11 flops / ~2e8 bytes  -> ~1300 flops/byte (compute-bound)
# elementwise gelu: ~1 flop / 4 bytes          -> ~0.25 flops/byte (bandwidth-bound)
強度是逐核心函式計算的;同一塊晶片對某個核心受運算限制,對另一個卻在挨餓。

屋頂線:一張圖,一個判決

屋頂線模型(roofline model)在對數—對數座標上,把可達效能(FLOPs/s)對算術強度作圖。有兩道天花板。一條斜線——記憶體屋頂——等於(峰值頻寬 × 強度):當位元組是瓶頸時,強度加倍速度就加倍。一條水平線——運算屋頂——是晶片的峰值 FLOPs/s。兩線相交處是脊點(ridge point)。脊點左邊的核心函式屬於記憶體頻寬受限;右邊則屬於運算受限。把你核心函式量測到的強度與吞吐量畫上去,到屋頂的差距就精確告訴你還有多少效能被浪費。

P_{\text{attainable}} \;=\; \min\!\left(P_{\text{peak}},\; I \times B_{\text{peak}}\right)

屋顶线判定:可达的 FLOPs/s 取计算上限与算术强度乘以峰值带宽两者中的较小值。

為什麼頻寬才是真正稀缺的資源

加速器從高頻寬記憶體(HBM)餵養它的張量核心——堆疊式 DRAM,每秒可供應數 TB,比一般 DDR 高一個數量級。然而即使是 HBM 也跟不上運算單元,這正是脊點落在每位元組數百次浮點運算的原因。這個教訓的適用範圍遠超單一核心函式:大型語言模型的訓練由大型 GEMM 主導,傾向受運算限制;而大型語言模型的解碼為了產生單一 token,要讀取整個權重矩陣,因此嚴重受頻寬限制。同一個模型、相反的régime——也是相反的最佳化策略。

這也是為什麼 FlashAttention 是一座里程碑。樸素的注意力核心函式會在 HBM 中具現化完整的 N×N 分數矩陣,使其極度受頻寬限制。FlashAttention 把分數保留在快速的晶片內 SRAM、從不寫出——藉此提高算術強度、把核心函式在屋頂線上往右滑,將一個記憶體挨餓的運算變成接近受運算限制的運算。這就是屋頂線的實際應用。

朴素注意力会在 HBM 中物化完整的 N×N 查询–键得分矩阵,使该核严重受带宽限制。

图示:注意力机制将查询、键、值向量通过 softmax 权重组合。

在實務中使用屋頂線

  1. 對核心函式做剖析:從 GPU 剖析器(如 Nsight Compute、PyTorch profiler)讀出實際達到的 FLOPs/s 與 bytes/s。
  2. 計算它的算術強度 = FLOPs / bytes,並把該點放到晶片的屋頂線上。
  3. 讀出判決:脊點左邊代表受頻寬限制——追求資料重用與融合;右邊代表受運算限制——追求佔用率與精度。
  4. 估算可改善空間:到相關屋頂的距離就是你可能的最大加速;若距離很小,就停手、去別處最佳化。
  5. 每次修改後重新剖析,看著那個點移動——在屋頂線上看不見的最佳化,多半什麼也沒做。