推理延遲的組成:先知道時間花在哪裡
優化之前先拆解。多數團隊優化錯地方,是因為沒量過各段耗時。
「模型好慢」是沒有行動力的描述。把一次請求的時間拆開,才知道該動哪裡。
五段時間
- 排隊:請求等待可用運算資源的時間。負載高時這段最大。
- 預填充(prefill):處理輸入 token,與輸入長度大致成正比。
- 首個 token(TTFT):排隊加預填充,使用者感知的「開始反應」時間。
- 逐 token 生成(decode):與輸出長度成正比,決定「打字速度」。
- 後處理:解析、驗證、寫入資料庫。
分開量測
import time
t0 = time.perf_counter()
stream = client.stream(prompt)
first = None
for i, chunk in enumerate(stream):
if first is None:
first = time.perf_counter()
ttft = first - t0
end = time.perf_counter()
print(f'TTFT {ttft*1000:.0f}ms 總計 {(end-t0)*1000:.0f}ms '
f'生成速度 {n_out/(end-first):.1f} tok/s')對症下藥
- TTFT 高、生成速度正常 → 縮短輸入、開前綴快取、或擴容降低排隊。
- TTFT 正常、總時間長 → 輸出太長,限制
max_tokens或改寫提示要求精簡。 - 兩者都高 → 資源不足,先看 GPU 使用率與批次大小。
串流能改善的是感知,不是總時間
開啟串流後總耗時不變,但使用者在幾百毫秒內就看到字,體感差異很大。互動式介面幾乎一定要開;批次處理則沒必要。
量測要看 p95 與 p99,不要只看平均。平均值 800ms 但 p99 是 12 秒的系統,使用者會覺得「常常卡住」。