Prompt Cache:别再为同样的 System Prompt 重算一遍
多轮对话里 System Prompt 每次都一样——500 Token 的固定前缀,每轮推理都要重跑一遍 Prefill。等于把同一段文字反复"读"几十上百遍。Prompt Cache 就是来省掉这件重复劳动的。
正常推理流程下,一个新请求进来先跑 Prefill(全 Prompt 的 K/V 全部算一次),然后进入 Decode(每步算一个新 Token)。如果 System Prompt 有 500 Token、用户输入 100 Token,Prefill 跑了 600 Token。第二次对话 System Prompt 一样、用户输入变成 80 Token——Prefill 又跑了 580 Token,其中 500 Token 跟上一轮完全一样。
Prefix Cache 的原理
Prompt Cache(也叫 Prefix Cache)不存完整的 KV Cache——它只存 Prompt 前缀部分的 K/V。新请求进来时,先拿 Prompt 的前 N 个 Token 去 Cache 里查——有没有匹配的前缀。有的话,这 N 个 Token 的 K/V 直接复用,Prefill 只算新增的部分。
Prefix Cache 的命中流程: 请求 1:Prompt = [SYS_500] + [USER_100] → Prefill 全部 600 Token → 缓存 [SYS_500] 的 KV → hash(SYS_500) → Cache 条目 请求 2:Prompt = [SYS_500] + [USER_80] → hash(SYS_500) 命中! → 跳过 500 Token 的 Prefill → 只 Prefill USER_80 部分(80 Token) → 500 Token Prefill 时间直接省掉多轮对话里,第一轮是冷启动(全量 Prefill),第二轮起 Cache 命中率接近 100%。一个客服机器人一天 10 万请求,90% 是第二轮及以后的对话——Prefill 节省的总时间非常可观。
Runtime 如何管理 Prompt Cache
CANN 的 Prompt Cache 实现在 Runtime 层,不在应用层。好处是跟 NPU 显存管理和 HCCL 通信直接打通,不用在 Host 和 Device 之间搬 Cache 数据。
Cache 维护逻辑:
- 每个 Prefix 用 Token 序列的 hash 做键,存在 NPU 显存里,不搬回 CPU。
- 新请求查 Cache——有命中就跳过对应 Prefill;未命中就完整 Prefill 后把 Prefix 写入 Cache。
- Cache 满了走 LRU 淘汰——最久没被命中的条目被清除,释放显存。
# Prompt Cache 管理——Runtime 侧简化逻辑classPromptCache:def__init__(self,max_gb=2):self.pool=acl.rt.malloc(max_gb*1024**3)self.entries={}# {hash: {kv_offset, size, last_access}}deflookup(self,prefix_tokens):key=hash(tuple(prefix_tokens))ifkeyinself.entries:self.entries[key]["last_access"]=now()returnself.entries[key]["kv_offset"]# NPU 显存地址returnNonedefinsert(self,prefix_tokens,kv_data):key=hash(tuple(prefix_tokens))offset=self.pool_alloc(kv_data.nbytes)acl.rt.memcpy(offset,kv_data)# 存进 Poolself.entries[key]={"offset":offset,"size":kv_data.nbytes,"last_access":now()}ifself.pool_free<256*1024**2:# 不足 256MB 时淘汰self.evict_lru()收益量化
一个 AI 客服:System Prompt 500 Token,每轮用户输入平均 100 Token。1000 并发,每个用户 10 轮对话。
不使用 Prompt Cache:每轮 Prefill 600 Token,总 Prefill Token 数 = 1000 × 10 × 600 = 6M Token。每次 Prefill 约 12ms(500+100 Token),每用户 10 轮 = 120ms Prefill 总时间。
使用 Prompt Cache:第一轮 600 Token Prefill(12ms),后 9 轮只有 100 Token Prefill(约 2ms)。每用户 10 轮 = 12 + 9×2 = 30ms。省了 90ms/用户——1000 用户省了 90 秒 NPU 时间。
什么场景不适合
每个请求 Prefix 都不一样——Cache 命中率接近零。Batch 小导致 Cache 插入即淘汰——Cache 没热起来就被清空。真正的收益集中在"大 Prefix、高频重复"的场景:客服机器人、代码助手(Tool 描述固定)、RAG 的 System Prompt。
参考仓库
cann-recipes-infer 推理 Recipes
Runtime 运行时
ATB Transformer 加速库
CANN 学习中心
