EASA

玩統計|筆記

LLM 微調現場筆記Fine-tuning, from GPU memory to alignment

微調大型語言模型時,幾乎每個決定,最後都是同一道題:這張 GPU 的記憶體,夠不夠?

曹郁欣 · 2026 年 10 月修訂 · 所有數字皆重新推導

記憶體試算Where the memory goes

選一個模型和微調方法,看看訓練時記憶體被誰吃掉。以參數量 Ψ 來說,全參數微調光是權重、梯度和 AdamW 狀態就要 16Ψ 位元組;LoRA 和 QLoRA 縮小的是後面幾項,FlashAttention 和梯度檢查點縮小的是 activations。

模型
方法
序列長度與批次
4,096 tokens
batch 1
省記憶體的開關
GPU 數量(ZeRO-3 / FSDP 分片)
—GB · 每張 GPU 的尖峰記憶體

    估算值,實際用量通常差在 ±20% 內。假設 BF16 混合精度、AdamW、LoRA rank 16 套在所有線性層;QLoRA 用 NF4 加雙重量化,嵌入層與輸出層維持 BF16;activations 用 Korthikanti 等人(2022)的公式。

    注意力,一步一步算Attention, one step at a time

    拿一句 6 個 token 的小例子,把一層、一個 head 的注意力完整算一遍。格子裡的數字都是瀏覽器即時算出來的;每一步右邊會換算成 Llama 2 7B、4,096 個 token 時的實際大小,看出記憶體在哪一步爆掉。

    Step 1 / 8

    正值負值遮罩(−∞)

    三個槓桿Three levers, three different terms

    省記憶體的技巧很多,但每一個只動到公式裡的某一項。先找出哪一項最大,再挑對的槓桿。

    LoRA · QLoRA

    縮小「要訓練的參數」

    凍結原本的權重 W₀,只學一個低秩更新 (α/r)·BA。梯度和優化器狀態只跟著 adapter 走:Llama 2 7B 在 r=16、所有線性層下,可訓練參數只有 4,000 萬,約 0.62%。QLoRA 再把凍結的權重壓到 4-bit NF4。

    動到:梯度、優化器狀態(QLoRA 也動到權重)

    FlashAttention · checkpointing

    縮小「activations」

    長序列時,注意力分數矩陣隨長度平方成長。FlashAttention 分塊計算、不把 s×s 矩陣寫回 HBM,結果完全相同;梯度檢查點只存每層的輸入,反向時再算一次。

    動到:activations

    ZeRO-3 · FSDP

    把模型狀態「分給多張卡」

    權重、梯度、優化器狀態切成 N 份,每張卡只放 16Ψ/N。代價是通訊量約為一般資料平行的 1.5 倍,需要好的卡間頻寬。activations 不會因此變小。

    動到:權重、梯度、優化器狀態(÷N)

    對齊階段,記憶體裡同時有幾個模型?Alignment, counted in models held in memory

    SFT 之後的偏好學習,差別不只在演算法,也在 GPU 上同時要放幾份模型。這也是 DPO 和 GRPO 會流行的實際原因。

    SFT監督式微調

    policy

    用 prompt/回答配對,教模型格式和任務。只有一個模型在訓練。

    DPO直接偏好最佳化

    policyreference

    拿「較好/較差」的回答配對直接算損失,不需要獎勵模型、也不需要取樣。損失裡一定要有凍結的 reference 模型,否則模型會離 SFT 版本越來越遠。學習率很小(約 5e-7),1–2 個 epoch。

    PPORLHF 經典做法

    policycriticreferencereward

    四個模型:要訓練的 policy 和 critic(價值模型),加上凍結的 reference 與獎勵模型。最有彈性,也最吃記憶體、最難調。

    GRPODeepSeekMath、R1 採用

    policyreferencereward 規則或模型

    拿掉的是 critic,不是獎勵。每個 prompt 取樣一組回答,用組內平均和標準差把分數標準化成 advantage。獎勵常是可驗證的規則,例如單元測試、數學答案比對(RLVR)。

    需要訓練凍結,只做推論可以是程式規則,不一定是模型

    上線之後:KV cache 的帳Serving: the KV cache

    推論時,每個生成過的 token 都要留下 K 和 V。公式是 2 × 層數 × KV heads × head 維度 × token 數 × 位元組。下面是 4,096 個 token、FP16 時,一條序列的用量;併發一多,佔滿 GPU 的往往是它,而不是權重。

    Llama 2 7BMHA,32 個 KV heads
    2.15 GB
    Llama 2 13BMHA,40 個 KV heads
    3.36 GB
    Llama 2 70BGQA,只有 8 個 KV heads
    1.34 GB

    70B 的 cache 比 13B 還小,原因就是 GQA:64 個 query heads 共用 8 組 K/V。DeepSeek 的 MLA 更進一步,只存一個壓縮過的潛在向量,官方數據是比 DeepSeek 67B 少了 93.3%。PagedAttention(vLLM)則是不改大小、改配置方式:用固定大小的區塊配置,把浪費從 60–80% 降到 4% 以下。