iT邦幫忙

2026 iThome 鐵人賽

DAY 18
0
Software Development

LLM infra 學習日記系列 第 18

Prefix Caching:相同 Prompt 為什麼不用再算一次KV?

  • 分享至 

  • xImage
  •  

它快取的不是 Prompt 文字

假設兩條 requests 是:

Request A = [system prompt][shared document][question A]
Request B = [system prompt][shared document][question B]

它們前面的 token IDs 完全相同。A 做完 Prefill 後,Attention 各層已經為這段 prefix 產生 K、V tensors。

B 不必再次對 shared prefix 執行 model forward:

載入 shared prefix 的 KV blocks
→ 只計算 question B
→ 開始產生第一個 output token

所以 Prefix Caching 省的是 Prefill compute,不是 tokenization,也不會讓後面的 autoregressive Decode 消失。

它也不是 semantic cache。「幫我摘要」和「請做摘要」意思接近,但 token IDs 不同,不能直接共用 KV。


一個高 reuse 的紙上 workload

假設 block size 是 4 tokens。四條 requests 都有:

16-token 相同 prefix + 4-token 不同問題 = 20-token prompt
情境 第 1 條 後 3 條 總 Prefill token work
無 reuse 20 3 × 20 80
有 Prefix Cache 20 3 × 4 32

這個例子省下 80 - 32 = 48 次 prompt-token computation,也就是 60%。

這只是 token work 手算,不代表 TTFT 一定降低 60%。真實時間還包含 queueing、Scheduler、hash lookup、剩餘 suffix、GPU kernel 與 sampling。


為什麼用 Block,而不是整條 Prompt 當 key?

vLLM 把 KV Cache 分成固定大小的 blocks。每個可快取 block 的 hash 由三類資料構成:

parent block hash
+ 這個 block 的 token IDs
+ LoRA / multimodal input / cache salt 等額外資訊

parent hash 很重要。即使某個 block 裡的 tokens 相同,只要前面的 context 不同,它的 KV 也不同,不能誤用。

查詢時會從第一個 block 開始,找出最長的連續命中 prefix;第一個 miss 之後就停止。

而且目前只快取 完整 blocks。如果 block size 是 4,兩條 prompts 前 10 個 tokens 相同:

可命中:前 8 tokens
仍要計算:第 9、10 token 與後續 suffix

因此「共同 prefix 有多長」和「實際 cache hit tokens」不一定相同。


vLLM V1 的 request 怎麼命中 Cache?

一條新 request 進入 Scheduler 後,主要路徑可以簡化成:

1. 對 prompt blocks 建立 hash chain
2. KVCacheManager.get_computed_blocks()
3. 找出最長的 full-block cache hit
4. 將命中的 tokens 記為已計算
5. allocate_slots() 引用 cached blocks,並替 suffix 配置新 blocks
6. Model Runner 只計算尚未完成的 tokens

Request 完成後,block 的 reference count 會下降。沒有 request 正在使用的 block 仍可留在 cache 中等待下一次 reuse;當 KV 空間不足,它才依 LRU free queue 被逐出。

還有一個細節:如果整條 prompt 都命中,模型仍需要最後一個位置的 logits 才能開始 sampling。因此目前實作至少會重算最後一個 token;受 block alignment 限制時,可能重算最後一個完整 block。


哪些情況容易 Hit?

Workload Prefix reuse
固定 system prompt 的聊天服務
同一份長文件的多輪問答
固定 few-shot examples、只更換問題
每次 prompt 都完全不同
相同文字但 chat template、tokenizer 或 LoRA 不同 不應直接共用

即使 workload 很適合,也可能因 KV Cache 壓力而 miss:cached blocks 不是永久保存,新的 requests 仍會把舊 blocks 淘汰。

另外,要求 prompt logprobs 的 request 在目前 V1 實作中會跳過本地 Prefix Cache lookup,因為它需要重新計算 prompt 才能取得那些 logprobs。


多租戶還有一個安全問題

Cache hit 可能反映在 latency 上。如果不同使用者能任意共享同一個 prefix cache,攻擊者可能用時間差推測某段內容是否曾被處理。

vLLM 支援把 cache_salt 放進第一個 block 的 hash。只有使用相同 salt 的 requests 才能共享 cached blocks,用來隔離不同 trust groups。


Reference


上一篇
Prefix Caching:相同 Prompt 為什麼不用再算一次?
下一篇
LLM Serving Benchmark:如何對serving system 做benchmark
系列文
LLM infra 學習日記19
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言