對應原題(Common ‧ Inference, Serving and GPU Performance)
- When would you choose vLLM vs SGLang vs TensorRT-LLM vs a custom stack? — Asked at: NVIDIA, Together AI
- How would you cut LLM serving cost by 10x? Enumerate every lever and rank them.
— Asked at: Microsoft, Amazon, NVIDIA, Cursor- Your p99 latency doubled after a deploy with no model change. Walk through the diagnosis.
— Asked at: OpenAI, Amazon, Databricks, Perplexity- What is chunked prefill, and why does it improve tail latency under mixed traffic?
- Explain disaggregated prefill/decode serving and when it pays for itself. — Asked at: Moonshot AI, Groq
🎯 什麼情境該想到我
當你「要選推論框架、要砍成本、或線上延遲突然壞掉」的時候。這一頁是 B 區所有機制的應用層。
⚙️ 怎麼用
一、框架選型
| 框架 | 設計重心 | 選它的理由 | 不選它的理由 |
|---|---|---|---|
| vLLM | PagedAttention 的發源地,通用高吞吐 | 生態最廣、新模型支援最快、上手最簡單、社群最大 | 極致單卡效能不如編譯式方案 |
| SGLang | RadixAttention(以基數樹管理 KV,跨請求自動共享前綴)+ 結構化輸出 | 多輪對話、agent、共享前綴極多的場景;約束解碼快 | 生態較新 |
| TensorRT-LLM | NVIDIA 官方,編譯式(先 build engine) | NVIDIA 硬體上的極致效能,尤其配 Triton;FP8/FP4 支援最完整 | 要 build engine(改配置就重 build)、模型支援較慢、運維重 |
| TGI | HuggingFace 生態整合 | 只剩既有部署維運 | 已進入維護模式、repo 已封存(README 只收小修,官方改推薦 vLLM/SGLang;查證 2026-10-15),新專案不要選 |
| llama.cpp / Ollama | CPU / Apple Silicon / 單機 | 本地開發、邊緣部署、Mac | 不是為多租戶高吞吐服務設計 |
| 自建 | 特殊硬體或極端規模 | 只有兩種情況:(1) 非 NVIDIA 的自研硬體(Groq、TPU)(2) 規模大到 1% 的改善值一個團隊 | 其他所有情況都是造輪子 |
(表中各框架的強弱定位是截至 2026-10 的判斷,非 benchmark 結論;TGI 狀態查證 2026-10-15。)
選型的務實順序:先 vLLM 跑起來 → 量出瓶頸 → 再決定要不要換。
「哪個最快」的 benchmark 隨版本變動極快(而且各家自己測自己贏),不要拿別人的數字做決策。
二、★ 降本十倍:槓桿排序
按投報率排,不是按技術含量排:
| # | 槓桿 | 量級 | 說明 |
|---|---|---|---|
| 1 | 不要呼叫 LLM | ∞ | 精確快取(同問題同答案)、規則能解的就別用模型、用分類器擋掉不需要生成的請求。最高的槓桿永遠是「不做」 |
| 2 | 模型路由 / 換小模型 | 5–20× | 絕大多數流量不需要最強的模型。用小模型處理 + 信心低時升級。這通常是單一最大的一筆 |
| 3 | 前綴快取 | 快取命中的 input 便宜 10×(部分新模型 20×) | 長 system prompt / few-shot / agent 迴圈。改個排序就生效。見 前綴快取 Prompt Caching。OpenAI/Anthropic 快取命中價多為原 input 的 0.1×,部分新模型 0.05×(查證 2026-10-15) |
| 4 | 量化 | 2–6× | 不只省一半權重,省下的顯存變成併發。見 GPU 記憶體估算 的 6× 那張表 |
| 5 | 連續批次 + 調大 batch | 2–20× | 若還在用靜態批次,這是免費的倍數。見 連續批次 Continuous Batching |
| 6 | 縮短 prompt 與輸出 | 2–5× | output token 比 input 貴約 5 倍(OpenAI、Anthropic 現行模型價目皆為 5×,查證 2026-10-15)——「請簡潔回答」是有現金價值的。壓縮 few-shot、去掉冗餘上下文 |
| 7 | 蒸餾出專用小模型 | 5–10× | 有穩定任務與足夠流量時最划算。見 知識蒸餾 |
| 8 | 批次 API / 離線化 | ~2× | 非即時的工作丟批次端點(OpenAI、Anthropic 的 Batch API 皆為 input/output 五折,查證 2026-10-15)。先問「這真的需要同步嗎」 |
| 9 | 硬體與採購 | 1.5–3× | 預留執行個體、spot、選對卡(decode 重頻寬、prefill 重算力) |
| 10 | 推測解碼 | 延遲 2–3× | ⚠️ 這是延遲優化,不是成本優化——高 batch 下反而更貴。見 推測解碼 Speculative Decoding |
(「量級」欄:#3、#6、#8 的價格比例已對 OpenAI/Anthropic 官方價目查證 2026-10-15;其餘倍數為經驗值,未查證。)
面試答法:「10× 不會來自單一技術。典型組合是 模型路由 5× × 量化 2× × 前綴快取 + 批次 ——而且我會先量清楚成本的組成(input/output token 比例、併發、快取命中率),再決定動哪個。盲目優化推論 kernel 是最常見的走錯方向。」
三、Chunked Prefill
問題:連續批次讓 prefill 和 decode 混在同一個 batch 裡。一個 8K token 的 prefill 要算幾十毫秒,這段時間所有正在 decode 的使用者全部卡住——他們看到文字突然停頓。
沒有 chunked prefill
step: │ D D D │ P(8K,一次算完,60 ms) │ D D D │
└─ 所有 decode 使用者卡 60 ms ─┘ ← p99 ITL 爆掉
有 chunked prefill(每步 token 預算 = 2048)
step: │ D D D +P₁ │ D D D +P₂ │ D D D +P₃ │ D D D +P₄ │
每步都混入一小塊 prefill,decode 幾乎不受影響
機制:設定每步的 token 預算(vLLM 的 max_num_batched_tokens),先塞滿 decode 的 token,剩餘額度拿來做 prefill 的一部分。
| 效果 | |
|---|---|
| ✅ p99 ITL 大幅改善,decode 變平順 | |
| ✅ 每步 token 數穩定 → GPU 利用率穩定 | |
| ❌ 那個長 prefill 自己的 TTFT 變差(被切成好幾步) |
一句話:拿長請求的 TTFT,換所有人的 ITL 穩定。 混合流量(長短 prompt 並存)下幾乎一定該開。
四、PD 分離(Disaggregated Prefill/Decode)
動機:prefill 和 decode 是兩種完全不同的工作負載(見 Prefill 與 Decode),硬塞在同一個池子裡,任何批次策略都是妥協。
┌──────────────┐ KV cache 傳輸 ┌──────────────┐
請求 ──▶│ Prefill 池 │ ═══════════════▶ │ Decode 池 │──▶ 串流輸出
│ compute-bound │ (RDMA/NVLink) │ memory-bound │
│ 大算力的卡 │ │ 大頻寬的卡 │
│ 小 batch │ │ 超大 batch │
└──────────────┘ └──────────────┘
好處:
- 徹底消除互相干擾——TTFT 和 TPOT 可以獨立最佳化到極致
- 各自用最適合的批次策略(prefill 不需要大 batch,decode 需要)
- 可以獨立擴縮——長 prompt 流量多就加 P 節點
- 可以用不同硬體——這正是 Groq / Moonshot 會問這題的原因
代價:
- KV cache 要跨節點搬。一條 4K 的 Llama-70B 序列是 1.25 GiB——沒有 RDMA / NVLink 等級的互連就是災難
- 架構複雜度、故障模式變多
- 小規模是淨虧
什麼時候值得:(1) 規模夠大,P 和 D 都能各自吃滿卡 (2) prompt 長度變異大 (3) SLO 對 TTFT 和 TPOT 都嚴格 (4) 有高速互連。
少於幾十張卡基本不值得 —— 用 chunked prefill 就好。
五、★ p99 診斷手冊:「沒改模型,p99 卻變兩倍」
這題考的是系統性排查,不是猜。順序很重要:
Step 1:先拆是 TTFT 還是 TPOT
p99 E2E ↑
├─ TTFT ↑ → 排隊?prefill 變長?→ 往 Step 2、3
└─ TPOT ↑ → batch 變大?KV 變長?preemption?→ 往 Step 4
沒有分開量這兩個,後面全是瞎猜。
Step 2:★ 輸入/輸出長度分布變了嗎(最常見的真兇)
「沒改模型」≠「沒改 prompt」。檢查:
- prompt 模板是不是加了東西(多塞了幾段檢索結果、多了一個工具定義)
- 輸出長度分布(改了
max_tokens?改了指示讓模型變囉嗦?) - 上游的 RAG 是不是多召回了幾段
prefill 的 attention 是 ——prompt 長 2 倍,TTFT 可能是 4 倍。
Step 3:★ 前綴快取命中率掉了嗎(第二常見)
改一個字的 system prompt,快取命中率就歸零。
- 看
cache_read_input_tokens的比例有沒有斷崖 - 有沒有人在 prompt 前面加了時間戳 / request ID(見 前綴快取 Prompt Caching 的經典坑)
- 工具定義是不是變成動態生成了(改工具定義會打掉整個快取)
Step 4:排程與顯存壓力
- preemption 率 —— 看 log 裡的 preempted 計數。被搶佔又 recompute 的請求就是 p99 的長尾
- KV cache 利用率 —— 接近 100% 代表已經在邊緣
- 等待佇列長度 —— TTFT 裡的排隊成分
max_num_seqs/max_num_batched_tokens有沒有被改
Step 5:部署本身
- 框架 / kernel 版本變了嗎(升級可能換了 attention 後端)
- TP/PP 配置變了嗎(TP 不小心跨節點 → 見 平行化策略)
- 副本數變少了嗎(HPA 設定、節點被驅逐)
- warmup 做了嗎(新 pod 的前幾個請求含 CUDA graph 捕捉與 JIT,特別慢)
Step 6:硬體與鄰居
- GPU 降頻(溫度、功率上限)、ECC 錯誤
- 共置的其他工作負載搶 PCIe / 網路
- 換了不同型號的卡(同一個 node group 裡混了 A100 和 H100)
Step 7:上游放大
- 重試風暴 —— 延遲一上升,客戶端 timeout → 重試 → 負載更高 → 更慢。這會把小問題放大成事故
- 有沒有人新接了一個高流量 client
答題框架:「先分層(TTFT/TPOT)→ 再看輸入分布 → 再看快取命中 → 再看排程壓力 → 最後才懷疑硬體。
我的經驗是九成的『沒改模型卻變慢』最後都是prompt 變長了或快取失效了。」
⚠️ 注意 / 什麼時候不適用
- 框架 benchmark 半年就過時。上面寫的是設計重心,不是效能排名。要選就自己用真實流量測。
- 降本槓桿會互相衝突:大 batch 省錢但傷延遲;推測解碼降延遲但高 batch 下加成本。先定 SLO,再談成本。
- 別在沒有 per-request 的 token 計數與成本歸因前談降本。沒有歸因就是瞎調。
- chunked prefill 的 token 預算要調。太小會讓長 prefill 的 TTFT 難看,太大就失去效果。
- PD 分離不要在小規模上做,複雜度成本遠大於收益。
- p99 診斷不要跳步。直接去 profile kernel 是最浪費時間的起手式。
🧪 我實際套用的紀錄
- 2026-09-20:從面試題庫展開。待辦:把 p99 診斷的 Step 1–7 做成 runbook。
🔗 相關
- Prefill 與 Decode —— 所有結論的依據
- 連續批次 Continuous Batching、PagedAttention 與 vLLM —— 框架的核心機制
- 前綴快取 Prompt Caching —— 降本第 3 槓桿,也是 p99 診斷第 3 步
- 量化 Quantization、GPU 記憶體估算 —— 降本第 4 槓桿的算法
- 推測解碼 Speculative Decoding —— 延遲而非成本
- 平行化策略 —— 部署配置
- 工具-LLM推論最佳化 —— 決策層摘要