10. 面试题
覆盖初级(概念与计算)、中级(机制与权衡)、高级(架构与生产)三档,共 14 题。
初级
1. KV Cache 是什么?为什么需要它?
KV Cache 是历史 token 在注意力层产生的 Key/Value 向量的缓存。自回归生成每步都要对全部历史做注意力,没有缓存就是 O(N²) 计算;缓存后每步只算新 token 的 K/V 并读取历史,计算降为 O(N)。代价是显存占用:每 token 需 2×层数×KV heads×head_dim×字节数。
2. 手算:Llama-3.1-70B(80 层、8 KV heads、head_dim 128)FP16 下每 token KV 多少字节?128K 上下文多大?
2×80×8×128×2 字节 = 327,680 字节 = 320 KiB/token。128K token ≈ 40 GiB。若 FP8 量化则减半为 20 GiB。
3. GQA / MQA / MLA 分别怎么降低 KV 占用?
GQA 多查询头共享少量 KV 头(如 64 Q heads 共享 8 KV heads),KV 占用降为 1/8;MQA 所有查询头共享一个 KV 头,更极端但质量有折损;MLA(DeepSeek)把 KV 压缩成低秩隐向量,等效每 token 几十 KB,是架构层压缩 KV 的代表。
4. Prefix caching 是什么?为什么能提高吞吐?
相同前缀的 KV 只算一次、存下来给后续请求复用。生产负载(system prompt、多轮对话、RAG)大量前缀重复,命中部分跳过 prefill,直接降低 TTFT 并释放 prefill 算力给新请求。
5. Copy-on-Write 在 KV block 管理里解决什么问题?
Beam search / 并行采样会让多条序列共享前缀 block。COW 让共享零拷贝(只加引用计数),某条序列要写某个共享 block 时才复制该 block,兼顾内存节省与写入隔离。
中级
6. RadixAttention 相比「整请求缓存」好在哪里?
按 token 序列组织缓存(radix tree),任意两条请求的任何公共前缀都能复用——整请求缓存只能命中完整前缀的请求。分叉处自动分裂节点,逐出按叶子 LRU 且保留公共祖先,复用率显著提升。
7. 为什么 Prefill 和 Decode 要分离?KV 在两者之间怎么传?
Prefill 计算密集(FLOPs -bound),Decode 显存带宽密集(bandwidth-bound),混布互相干扰、资源利用率都低。分离后 KV 经 Transfer Engine(RDMA/NVLink)按 block 从 prefill 节点搬到 decode 节点,并按 token 顺序流水线传输——首个 block 到达即可开始 decode,TTFT 不受全量传输时间拖累(Mooncake、Dynamo 的架构核心)。
8. 分层 KV 缓存(GPU→CPU→SSD)什么情况下是赚的?什么情况下不如重算?
命中收益 = 省下的 prefill 时间;命中成本 = 慢层读取 + 快层写回 + 驱逐副作用。prefill 成本通常在毫秒级以上而搬运在微秒~毫秒级,长前缀命中几乎总是赚的;短前缀(几百 token 以内)可能重算更便宜。所以提升策略要带成本闸。
9. Cache-aware 路由为什么不能只看命中率?
纯命中路由会把同前缀请求全部导向同一实例,造成热点与排队,反而拉长 TTFT。生产路由把命中长度与负载/队列深度加权打分(Dynamo Smart Router、SGLang cache-aware LB),有的还叠加索引滞后惩罚。
10. FP8 KV 量化的收益与风险?
收益:显存减半(等价于 KV 池容量翻倍)、传输与搬运同比例加速。风险:注意力精度下降,长上下文更敏感;需要 kernel 支持(FlashMLA/FlashInfer);建议热数据 FP16、冷数据 FP8 分层量化,并用长上下文基准回归验证。
11. 请求结束后它的 KV 去了哪里?
引用计数归零的 block 不立即释放,标记为可逐出缓存供后续请求复用;显存紧张时按 LRU 先下沉到 CPU/SSD(demote-first),慢层也满才真正丢弃;同时向全局索引发注销事件更新路由视图。
高级
12. 设计一个跨 8 实例共享的 KV 缓存池:索引、一致性、路由怎么设计?
索引:实例本地 radix tree 做精确匹配;路由侧维护「前缀哈希 → 实例列表」的近似索引,用缓存事件(注册/逐出)增量更新,允许滞后。一致性:block 内容不可变(生成完即冻结),唯一的一致性问题是谁还持有引用——用引用计数 + 心跳超时兜底,无需分布式事务。路由:两层(Gateway 按前缀分片粗选池,池内细选命中实例),打分含命中长度、队列深度与索引置信度;控制面故障时整体退化为普通负载均衡。
13. Mooncake 为什么强调 Transfer Engine 而不是直接用 RDMA 库?
工程复杂度在「调度」不在「发送」:拓扑感知选路(NVLink/PCIe/RDMA 分层)、多 NIC 带宽聚合与多流并发、批量异步提交不阻塞引擎主循环、链路故障自动切换、跨传输后端统一抽象。官方数据 4×200Gbps RoCE 下 ~87 GB/s(约为 TCP 的 2.4 倍),说明传输层的价值在把物理带宽兑现成有效吞吐。
14. 上线 KV 缓存层之前,你会建立哪些指标与护栏?
指标:prefix 命中率(总/各层)、路由预测失效率、逐出与下沉速率、传输带宽利用率、TTFT/TPOT 分位。护栏:Store 故障自动降级为纯显存缓存;控制面故障降级为纯负载均衡;提升策略成本闸防慢层拖尾;逐出优先级保护公共前缀与活跃会话。预算:给「缓存未命中率」设 SLO(如 < 30%),它是 TTFT 长尾的直接来源。