Prefill 與 Decode(預填充與解碼)
又稱:預填充 · prefill · decode · 解碼階段 · TTFT
一次生成的兩個階段:prefill 一口氣平行讀完整個 prompt(算力瓶頸,決定首字延遲);decode 之後一個 token 一個 token 地生成(記憶體頻寬瓶頸,決定吐字速度)。
你會在什麼時候遇到它
當你第一次注意到「送出後卡一下才開始吐字,之後就很順」、或在供應商規格頁看到 TTFT 和 tokens/s 兩個指標並排時,就需要這個概念。不懂這兩個階段,你會把延遲歸錯因:以為首字慢是模型差(其實是 prompt 太長),或以為吐字慢是網路爛(其實是頻寬和模型大小)—— 然後往錯的方向優化。
打個比方
像口譯員工作:先聽完整段發言(prefill —— 一口氣、整段可以平行處理),再開始逐句翻譯(decode —— 一次只能說一句,且每說一句前都要在腦中快速重過全部筆記)。發言越長,開口的等待越久;翻譯越長,總時間越久 —— 兩段的瓶頸完全不同。
最小範例
送出一段長 prompt 之後,伺服器上發生的事:
[階段一 prefill]
整個 prompt 的所有 token 一次平行算完
順手把每一層的中間結果存成 KV 快取
→ 瓶頸:算力(大量矩陣運算)
→ 決定:你等多久才看到第一個字(TTFT)
[階段二 decode]
每生成一個 token:把整個模型的權重+已生成的
KV 快取從記憶體搬進計算單元,算出下一個 token
→ 瓶頸:記憶體頻寬(算得少、搬得多)
→ 決定:吐字速度(tokens/s)這個區分解釋了幾乎所有延遲疑惑:prompt 越長,prefill 越久、首字越慢(但開始吐字後速度不變);輸出越長,decode 輪數越多、總時間越久(但首字不受影響)。也是為什麼供應商把「輸入 token」和「輸出 token」分開計價 —— 兩個階段的成本結構本來就不同。
最常搞錯的地方
- 以為 decode 慢是「算力不夠」,想靠更強的計算單元加速吐字。decode 每一步的計算量很小,時間幾乎都花在搬運權重和 KV 快取上 —— 瓶頸是記憶體頻寬。這也是為什麼量化(把權重變小)常常能直接提升吐字速度。
- 以為多輪對話中,之前輪次的 prompt 一定全部重算,或反過來以為完全不用重算。實際上 KV 狀態可以在會話內複用(prompt caching);複用命中時 prefill 大幅變便宜 —— 這就是供應商「快取輸入較便宜」定價的由來。