资讯动态

SGLang 前缀缓存实战:RadixAttention 如何让重复前缀省下 3–5 倍计算

发布时间:2026/9/2 23:00:55 来源:尧图企业网站定制
SGLang 前缀缓存实战RadixAttention 如何让重复前缀省下 3–5 倍计算【免费下载链接】sglangSGLang is a high-performance serving framework for large language models and multimodal models.项目地址: https://gitcode.com/GitHub_Trending/sg/sglang本文围绕 SGLang 的 RadixAttention 前缀缓存展开它用一棵基数树Radix Tree记录「前缀 → 已算好的 KV 缓存位置」的映射新请求进来先查树、命中多少就免算多少。全文从真实部署场景出发讲清工作原理、最小可运行示例、加速来源、场景化用法、调参手册和常见坑。一个真实场景客服机器人的「每次都在重算」先讲个具体画面。某团队用 SGLang 部署了一个客服机器人每条请求都带着同一段约 2000 token 的知识库摘要和角色设定开头后面才是用户的具体问题。高峰期一小时几千条请求GPU 的算力几乎全花在这段「每次都一样的开头」上——同一个 2000 token 的 prefill 被反复算了几千遍。SGLang 为此专门做了 RadixAttention把已经算过的 KV 缓存按前缀持久化在一张基数树里基数树可以理解成「压缩版前缀字典树」相同前缀只存一份并且默认开启。第二个请求带着相同开头进来时调度器直接从树上找到已算好的 KV 张量索引跳过这部分 prefill只计算新增的 token。效果不是「快一点」而是同一批请求里后到请求的首 token 延迟TTFT可以砍掉一大截GPU 的 prefill 吞吐同步放大端到端常见 3–5 倍的加速区间具体取决于前缀重合度。前缀缓存到底解决什么问题一段前缀一份计算用两个比喻把痛点说透。快递驿站分拣。没有前缀缓存时每个包裹请求都要从产地模型第一层开始走完全程。驿站早该建立分拣规则同一条路前缀的包裹到达同一站之后的路可以共用。RadixAttention 就是那张「按前缀分区」的分拣表——token 序列是地址共同前缀越长越晚到的包裹越不用重走老路。图书馆按书架编号。每个「已经读过的前缀」占一个书架位KV 缓存的物理位置编号写进目录树。新读者报出书名开头管理员顺着目录找到最远的那个共同前缀直接从下一本接着读。痛点拆开看是两条因果链成本链前缀重复 → prefill 重复计算 → GPU 计费时间被浪费。因为 prefill 阶段是算力密集型的一段 2000 token 的公共前缀每多算一遍就多烧一遍等量的矩阵乘法。延迟链前缀重复 → TTFT 必须等完整 prefill 算完 → 用户等待时间里有一大段是「白等」。命中缓存后这段等待直接消失只剩新增 token 的计算时间。所以前缀缓存的收益不是玄学它能被直接量化每命中 1 个 token就省掉 1 个 token 的 prefill 计算。命中率是唯一的杠杆。一张图看懂 RadixAttention 的工作方式整个机制可以压缩成「进来查树 → 命中则复用 → 算完插树 → 空间不够再淘汰」四步对应到源码两个核心文件就够了树本体[radix_cache.py](https://link.gitcode.com/i/f21b0ef418d88df98eb7f361ff5fd976)。match_prefix找最长已缓存前缀insert把新算的 KV 挂回树上evict负责腾空间。每个TreeNode上维护着lock_ref引用计数请求在用就保护该节点不被淘汰和last_access_timeLRU 排序依据。开关与参数[server_args.py](https://link.gitcode.com/i/52d81e3484c60450db7c0a6f5664f701)。--disable-radix-cache可整体关闭--page-size、--radix-eviction-policy、--enable-hierarchical-cache都在这张参数表里。一句话总结数据流请求的 token 序列是钥匙树里存的是「钥匙 → KV 张量物理位置」的映射命中即省算算完再存回去。5 分钟跑通从启动服务到验证命中你马上能拿到的东西一条启动命令 三次请求亲眼看到缓存命中。第一步启动 SGLang 服务前缀缓存默认开启无需额外参数# 前缀缓存默认启用--page-size 控制每页 token 数默认 1 python -m sglang.launch_server \ --model-path Qwen/Qwen2.5-7B-Instruct \ --port 30000第二步发三次「同前缀、不同结尾」的请求PROMPT以下是公司FAQ摘要……2000 token 的公共前缀…… 问题 # 第一条缓存为空全量 prefill最慢 curl -s localhost:30000/generate -d {\text\: \${PROMPT}退货政策是什么\} # 第二、三条前缀命中只算最后几个 tokenTTFT 明显下降 curl -s localhost:30000/generate -d {\text\: \${PROMPT}运费怎么算\} curl -s localhost:30000/generate -d {\text\: \${PROMPT}几天能到\}验证是否命中有两个抓手# 1) 服务信息接口cache_hit_rate 会随重复前缀请求上升 curl -s localhost:30000/get_server_info # 2) Prometheus 指标中也暴露 gpu_prefix_cache_hit_rate curl -s localhost:30000/metrics | grep prefix_cache_hit看到cache_hit_rate从第一条请求的低值逐步爬升就说明树在正常工作。想彻底关掉做对照实验加--disable-radix-cache即可。它凭什么快 3–5 倍把命中率翻译成省下的计算先给结论加速不来自单次请求变快而来自「重复前缀」从计算图里消失了。因果链是这样的一批请求共享同一段前缀长度 P token只有第一个请求付出 P 次 prefill 的计算后续请求的这段直接查表拿到 KV 索引省下的 prefill 时间线性叠加到 GPU 批处理吞吐上TTFT 同步下降如果前缀长到超出 KV 池容量后被 LRU 淘汰加速就打折——命中率是上限淘汰策略决定你能吃到多少。用「省下的 token 数」而不是百分比来表达收益更直观。假设公共前缀 P 4000 token一批 100 条请求缓存策略这批请求实际付出的 prefill 计算量相比全量重算省掉的部分每次请求独立重算无缓存100 × 4000 40 万 token0RadixAttention 前缀全命中1 × 4000 各请求独立部分约 39.6 万 token 的 prefill命中率 50%部分被淘汰约 20 万 token约 20 万 token换算成体感prefill 占大头的工作负载里前缀部分省掉九成计算对应的就是 TTFT 从「等整段算完」变成「等最后几个 token 算完」端到端 3–5 倍的加速区间就是这么来的。前缀越短、请求越离散、KV 池越紧张收益越接近 1 倍——它不是魔法是「别算第二遍」的算术。这张饼图传达的重点是缓存把最贵的部分从「算力」变成了「显存读取」算力被腾出来给真正的新 token。把前缀缓存用起来四类高命中场景前缀缓存的收益 前缀重合度 × 前缀长度 × 请求频次。下面四类业务天然凑齐这三个条件。客服知识库问答。每条请求都带「角色设定 知识库文档 工具说明」三段固定内容只有最后的用户问题变化。把这三段稳定放在 prompt 最前面重合度接近 100%是最典型的受益场景。Agent 工具调用循环。Agent 每轮都会把「系统指令 工具 schema 历史动作记录」重新拼进 prompt。历史只增不改每一轮都在复用上一轮的前缀——轮数越多省得越多。关键约束历史部分不要每轮重排或改写前缀一变树就断在第一个分叉处。RAG 长文档问答。对同一份 5 万 token 的文档提 20 个问题文档 chunk 放在前缀位置20 条请求只付 1 次文档的 prefill 成本。文档切换频率越高命中率越低这时就该考虑下一节的 HiCache。评测批量跑分。benchmark 批量请求往往共享同一题面模板或 system prompt。把同模板请求排在一起提交比打散提交命中率高一档——连续提交对树很友好打散则反复制造分叉。四类场景的共同操作原则一句话固定内容前置、可变内容后置、别动已经发过的部分。调优与进阶一张调参手册把分散的机制整理成这张表参数名全部对应实际的--启动参数调什么参数 / 机制默认什么时候动它预期效果命中率cache_hit_rate/get_server_info与/metrics中gpu_prefix_cache_hit_rate—任何调优前先读它长期低于 30% 时先排查 prompt 结构再谈调参整体开关--disable-radix-cache不关闭做 A/B 对照实验关闭后 prefill 全量重算可做收益归因页粒度--page-size1配合分页注意力 / 稀疏 KV 特性时按后端要求调整页越大对齐浪费越多管理开销越小淘汰策略--radix-eviction-policylru/lfu/slru/prioritylru访问模式不均衡、少数热前缀反复出现 →lfu或slru更稳热前缀留存时间变长命中率上限提高长前缀跨请求留存--enable-hierarchical-cache--hicache-ratiocache 模式默认 2.0即主机 KV 池 2 倍设备池关闭前缀总长超过 GPU 容量、主机内存充足GPU 淘汰的前缀下沉到主机内存重命中时搬回省一次完整 prefillHiCache 写策略--hicache-write-policywrite_back/write_through/write_through_selective—主机带宽紧张时选 selective只写热数据减少无谓的主机写入分块前缀缓存--disable-chunked-prefix-cache默认开启面向 DeepSeek 系模型的分块前缀处理开启短序列为主的负载分块簿记开销不划算时关闭短请求省掉分块开销命名空间隔离RadixKey的extra_key区分 LoRA / 多版本 RAG 上下文无多 adapter、多版本知识库混跑不同extra_key的条目互不串用避免脏命中三个经验值供参考命中率长期 30%别急着调参先检查 prompt 拼装顺序是不是把可变内容放在了前面命中率 60% 且 TTFT 已经很低显存可以挪给更大的 batch并发上去了总成本反而降开了 HiCache 之后命中率仍掉说明前缀总量超过「GPU 主机」两层之和该考虑第三层存储后端如 mooncake、hf3fs、aibrix 这类见mem_cache/storage/目录。常见误区与踩坑实录问命中率很高为什么 TTFT 没降多少查请求顺序。前缀缓存是「按到达顺序」吃的——第一批全量算后面才受益。如果你的压测是单条串行发前几条请求延迟难看的换成并发压测整体 TTFT 和吞吐才体现真实收益。问system prompt 里加了一行当前时间戳命中率直接腰斩对而且只保留到第一个不同 token 为止。前缀匹配严格从左到右第一个不同的 token 之后全部重算。时间戳、request_id、每次变化的占位符这类字段要么挪到 prompt 末尾要么改成完全一致的静态文案。问显存没满缓存为什么还会被淘汰KV 池是独立分配的模型权重、激活、batch 预留之外才轮到 KV 池。而且请求正在解码时它占用的节点lock_ref 0不参与淘汰请求结束才释放。所以「显存占用 70%」和「KV 池水位」是两回事看/get_server_info的 token 用量比看 nvidia-smi 更准。问多个 TP rank前缀树不会各算各的吧不会错乱。KV 缓存按 TP 切分后各 rank 维护自己那份分片匹配长度由调度器统一决策。监控里的gpu_prefix_cache_hit_rate是调度器视角的统一口径不用担心多卡数据不一致。问前缀缓存会「污染」输出吗A 请求的 KV 被 B 用错了匹配键是完整 token 序列可加extra_key命名空间B 的前缀必须逐 token 等于树里已存前缀才会复用不同 LoRA、不同 adapter 走不同的extra_key物理上不会串用。问多轮对话历史越滚越长缓存还划算吗划算。每轮「历史 新问题」里历史部分是严格的前缀扩展天然高命中真正开始吃缓存的是第 2 轮起的每一轮。第 1 轮没有前缀可复用别把它算进收益预期。问开了 HiCache延迟是变好还是变坏分层看命中 GPU 层的请求不受影响命中主机层的请求多了「内存搬回 GPU」的传输比纯 prefill 快、比 GPU 直取慢——总体仍是赚的因为省掉的是完整的逐层计算。只有主机带宽被写策略打满时才会劣化这时换write_through_selective。写在最后把整件事收回业务口径前缀缓存把「重复前缀」从计算账单里划掉换回来的是三样东西——更低的单次 TTFT、更高的单卡并发、以及按 token 计费的推理成本直接缩水。对短 prompt 的单条请求它是锦上添花对带长 system prompt、长文档、长 Agent 历史的推理服务它是「同一张卡服务两到三倍流量」的关键开关。前缀缓存不改变模型它改变的是模型该被计算几次——而「少算」永远是推理系统里最便宜的性能。【免费下载链接】sglangSGLang is a high-performance serving framework for large language models and multimodal models.项目地址: https://gitcode.com/GitHub_Trending/sg/sglang创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价