尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

KV Cache 原理与显存优化:从 PagedAttention 到云上 vLLM 部署实战

发布时间:2026/9/26 4:29:40

资讯中心
01
ARTICLE

KV Cache 原理与显存优化:从 PagedAttention 到云上 vLLM 部署实战

KV Cache 原理与显存优化:从 PagedAttention 到云上 vLLM 部署实战
1. 从“云上跑开源模型”说起KV Cache 是谁为什么绕不开先抛一个很多人都遇到过的场景你在云厂商买了GPU实例高高兴兴把 Llama、Qwen 这类开源模型用 vLLM、TGI 或者 Ollama 跑起来结果一压测就傻眼——并发一上去显存直接爆掉或者吞吐量低得离谱单请求成本居高不下。这时候你去看监控会发现一个几乎占满了显存预算的“隐形大户”KV Cache。KV Cache 不是某个框架的私有概念它是 Transformer 架构自回归解码机制的必然产物。简单说大模型生成文本是一步步来的每生成一个新 token都要计算这个 token 对前面所有 token 的注意力分数而注意力的计算需要用到“Key”和“Value”两组向量。如果不做缓存每生成一个新 token 都得把前面整段对话重新算一遍计算量随序列长度呈平方级增长那模型服务根本没法商用。所以 KV Cache 做的事就是把历史 token 的 Key、Value 向量存下来后面生成新 token 时直接拿去参与注意力计算。你可以把它理解成做饭时的半成品备料——菜还没下锅葱姜蒜提前切好放那儿后面每炒一道菜都直接用不用重新洗菜切菜。对云厂商来说KV Cache 的重要性不只是“提速”这么简单。同一个 GPU 实例上能并发塞多少请求、每个请求能支持多长的上下文、长对话用户为什么越聊越贵这些问题的根子全在 KV Cache 上。它不像模型权重那样“加载一次就能反复用”而是每个请求、每个独立会话都要各自占一份并且随着对话变长不断膨胀。换句话说KV Cache 是模型服务中“实时性最强、弹性最差”的一类显存资源也是最考验工程水平的地方。这篇文章我会从 KV Cache 的底层原理讲起接着拆解云厂商里主流的开源推理框架以 vLLM 为代表是怎么管理这块缓存的再给出一套可以直接参考的部署参数、排查思路和避坑经验。无论你是刚入门做模型服务的小白还是已经在生产环境调优的工程师看完应该都能搞清楚云上开源模型服务的 KV Cache到底是怎么设计出来的。2. KV Cache 是怎么算出来、又占了多少显存想弄明白云厂商怎么做缓存管理先得把 KV Cache 的“物理形态”和“占用量”摸清楚。这一节我会把计算公式和典型数字摆出来后面你部署的时候可以直接套用。2.1 自回归解码里的 prefill 和 decode任何一个生成式大模型在推理时都分成两个阶段。第一个阶段叫 prefill预填充也就是你输入一整段 prompt 给模型模型对这段 prompt 做一次完整的前向计算把每一步注意力计算需要的 Key、Value 向量全部算出来并写入缓存。第二个阶段叫 decode解码模型每生成一个新 token就基于缓存中的历史 KV 向量只针对新 token 做一次自注意力计算然后把新 token 的 KV 也追加到缓存里。这里的关键是decode 阶段是一个 token 一个 token 串行生成的每次只算一个 token。你有没有想过明明 GPU 是并行计算设备为什么大模型生成不能多token一起出来因为在自回归架构里生成下一个 token 必须依赖前一个 token 的结果这个依赖关系从数学上就定死了。所以一个 GPU 可以同时处理很多个请求不同请求的 token 生成相互独立但单个请求内部的 token 只能挨个出。KV Cache 的价值就在于decode 阶段省掉了对历史 token 的整体前向计算只做增量计算这也是推理服务吞吐量能提上去的核心原因。如果你把 KV Cache 关掉让模型每生成一个 token 都从头算一遍完整序列那生成 1000 个 token 的耗时就不是生成 100 个 token 的 10 倍而是大约 100 倍。因为每次完整前向计算的代价随序列长度增长。做过算法题的朋友应该马上联想到那不就是每次循环都重新累加数组么典型的 O(n²) 复杂度。缓存就是把这个过程从 O(n²) 降成了 O(n)。2.2 一个 token 的 KV Cache 有多大要理解 KV Cache 为什么“吃显存”先得知道每个 token 的 KV 向量占用多大。这个值可以用一个非常简单的公式估算KV_Cache_每token字节数 2 × num_layers × num_kv_heads × head_dim × dtype_bytes其中 num_layers 是 Transformer 层数num_kv_heads 是注意力头的数量准确说是 KV 头的数量head_dim 是每个头的维度dtype_bytes 是存储精度FP16 是 2 字节FP8 是 1 字节。前面乘的 2 是因为每个 token 都要同时保存 Key 和 Value 两份向量如果再乘上批量大小就是这一批请求每个 token 的总占用量。拿 Llama-2-7B 举例它有 32 层每层 32 个注意力头每个头的维度 128用 FP16 精度。那么它每个 token 的 KV Cache 占用是2 × 32 × 32 × 128 × 2 524,288 字节 ≈ 512KB看起来单 token 只有 512KB但你要注意这是“每个 token 都要占”的空间。如果模型支持 4096 token 的上下文一个完整长度上下文请求就需要 512KB × 4096 2GB 显存这还没算模型权重和计算中间量。如果上下文扩大到 32K那就是 16GB几乎占满一张 A100 40GB 版显存的一小半。这就是为什么长上下文模型部署特别吃显存也是为什么 KV Cache 优化在云端模型服务里被反复讨论。我列一张常见模型参数的估算表方便你规划显存模型规模层数KV头数head_dim上下文长度FP16每token占用满上下文KV Cache占用7BLlama-232321284096512KB2GB7BQwen2.528412813107264KB8GB13BLlama-240401284096640KB2.5GB70BLlama-38081288192256KB2GB注意一个有意思的现象像 Qwen2.5 这样的新模型用了 GQA分组查询注意力KV 头数大大减少只有 4 个头所以每 token 的 KV 占用反而不如老模型高。这也是绕过“显存不够”的一个思路选模型时就把 KV Cache 的“单 token 成本”算进来。2.3 KV Cache 和请求成本的关系为什么长会话越来越贵网上有句很流行的话“为什么一个会话等待几个小时之后耗费会大涨”原因就在 KV Cache。你和一个模型连续聊了几个小时上下文积累了几万甚至十几万个 token那么那段时间里 GPU 显存里一直压着你这个会话的 KV Cache。假设上下文到了 32K tokenQV 存储就要 16GB这还不算中间计算缓冲。占着 16GB 显存的会话几乎把一张高配 GPU 的一半产能锁死了其他请求能进来的就少了单请求成本自然水涨船高。更隐蔽的是如果模型服务端把空闲会话的缓存逐出了也就是释放了这部分显存用户隔了几个小时再回来发消息服务端发现缓存不在了就不得不把你之前聊过的所有历史内容重新做一遍 prefill把历史上万 token 的 KV 重新算一遍。这个重新计算的过程耗时非常明显用户体感就是“卡了几十秒”而云厂商这边是实打实耗费了一遍 GPU 算力。这类问题业内叫“缓存失效”也是 KV Cache 缓存管理最需要解决的线上问题之一。3. 云厂商部署场景里KV Cache 到底是怎么管理的前面讲了 KV Cache 是什么、占多少内存接下来就是重头戏云厂商在开源模型服务里到底怎么把这块缓存调度好。如果你看过一些资料一定会频繁听到 vLLM、PagedAttention、前缀缓存这些词。这一节我逐个拆开讲并用生活化的类比帮你建立直观理解。3.1 vLLM 的 PagedAttention把显存当操作系统内存来管先问一个问题如果让你给每个请求预分配 KV Cache 空间你会怎么设计最简单粗暴的方案是每个请求进来自动分配一个能容纳最大上下文长度的连续显存块。这个方案看着省事实际跑起来惨不忍睹。因为绝大多数请求不会真的把上下文用满预分配的显存大量闲置更麻烦的是当某个请求刚开始只占了一点空间后来上下文增长原始分配的内存块不够用了就得搬数据到更大的连续区域这种“大块连续内存搬移”在并发场景下几乎是灾难碎片化严重、分配效率低。vLLM 提出并实现了 PagedAttention分页注意力思路直接借鉴了操作系统里的虚拟内存分页机制。它把 KV Cache 切成一个个固定大小的“块”block默认一个块能存 16 个 token 的 KV。每个请求只按需持有若干个不连续的块通过一张“块表”block table记录它用了哪些块、各块存的是什么位置的数据。生成新 token 时从空闲块池里取一个块挂到块表里而不是像连续内存那样必须“找一块大的、相邻的空间”。我打个比方你就懂了传统方式相当于你搬家时必须找一套和你所有家具正好匹配的大房子还得整套一起买PagedAttention 相当于你把东西分装进标准尺寸收纳箱散放在仓库里手上只拿一张存储位次表需要什么去对应位置取就行。仓库里任意位置只要有空就能放房间利用率自然上去了。PagedAttention 带来的实际收益非常直接物理上显存碎片减少了同类模型在相同 GPU 上并发能力明显提升vLLM 官方公开数据是说吞吐量能达到传统方案的数倍。这也是为什么现在云厂商部署开源模型服务vLLM 几乎成了默认选项。3.2 显存分配的比例账模型权重、KV Cache、激活值如何分部署时最核心的显存规划是跑模型不能只给模型权重留显存还得同时放 KV Cache 和前向计算过程中产生的激活值activation。如果这三个预算算错了模型要么加载失败要么跑起来就 OOM。vLLM 里有个参数叫 gpu-memory-utilization默认是 0.9。意思是vLLM 最多使用 GPU 总显存的 90%剩下的留给驱动、CUDA context、碎片化缓冲等开销。这 90% 里首先要装入模型权重然后留出前向计算需要的 CUDA graph 空间和激活值缓冲最后剩下的全部划进 KV Cache 内存池。举个例子A100 80GB 显存gpu-memory-utilization 设为 0.9那 vLLM 可支配约 72GB。加载一个 Qwen2.5-14BFP16 权重占约 28GB预留 CUDA graph 和激活值约 2GB那么剩下约 42GB 就是 KV Cache 池。这块池子能容纳多少并发取决于每个请求的平均 token 长度和 KV 每 token 占用。如果你用的是 GQA 架构模型每 token KV 占用小42GB 可以支撑很大的并发规模如果用的老架构模型可能支撑不了多少并发。这里我建议你部署前一定亲手算一遍账别拿“别人说能扛多少并发”直接抄。模型改一个版本KV 头数可能变支持的最大上下文可能变显存规划就得跟着变。3.3 Continuous Batching让 KV Cache 池子始终有活干早期推理框架喜欢用静态 batching就是攒够一批请求后一起前向计算所有请求同步推进一个请求生成了 100 token其他请求也得等它到 100 才能一起结束。这样做的坏处是一批里有的请求已经生成了 2000 token占用了 2000 token 的 KV Cache有的请求刚进来只占了 200 token但显存是按这批请求里最长的那个来预留的于是大量空间被浪费。现在主流的做法是 continuous batching连续批处理也叫迭代级调度。调度器每步只做一次生成生成完就检查哪个请求已经结束、可以释放 KV Cache 了哪个新请求在队列里等着可以插进来这样每个时刻 GPU 都在做有效的 decode 计算KV Cache 池的利用率被压到很高。这也是 vLLM 能实现高吞吐的关键原因之一。你可能听过“批处理对 GPU 越友好”这句话原理是 GPU 的 SIMT 架构适合大规模并行同一时间处理的请求越多算术强度越高、利用率越好。但请求数并不是越多越好因为每个请求都要占 KV Cache 空间一旦 KV Cache 池用尽新的请求只能排队等待。所以云厂商的服务端会综合“显存容量”和“并发请求量”做调度本质就是在 KV Cache 预算内尽量把 batch 塞满。3.4 前缀缓存多个请求共享重复上下文聊到 KV Cache 优化真正体现“缓存命中”价值的是前缀缓存prefix caching。原理很朴素很多请求的上文是重复的比如所有请求都带同一个超长系统提示词或者多轮对话里后续轮次都包含前面的历史。如果这些公共前缀能共用同一份 KV Cache那显存占用和计算开销都能省下一大块。vLLM 的实现叫自动前缀缓存Automatic Prefix Caching它用一个哈希表记录一段文本序列对应的 KV Cache 块。新请求进来时从最长的公共前缀开始复用以前的 KV 块只有不匹配的部分才重新计算。SGLang 里的 RadixAttention 更进一步用基数树管理所有请求的历史前缀可以支持任意公共前缀的复用而不一定从开头对齐。这在大量相似 prompt 的线上推理场景里收益非常明显。我记得有个真实案例给模型的 system prompt 特别长两千多 token每次请求都要让模型重新 prefill 一遍。打开前缀缓存后系统提示词部分的 KV 直接从缓存块表里引用每个请求省掉的 prefill 时间非常可观单请求延迟降了 30% 以上整体吞吐也上来了。这就是用户们常说的“AI 缓存命中”真正落地的地方。3.5 多卡并行时KV Cache 怎么跟着切单张 GPU 装不下一整个大模型时云厂商标准做法是把模型拆分到多张 GPU 上最常见的并行方式是张量并行Tensor Parallelism。在 Transformer 的注意力层里多头注意力的每个头是可以独立计算的所以可以把不同头分配到不同 GPU 上各自负责一部分注意力计算。随之而来的是每个 GPU 只需要保存它负责的那部分头对应的 KV Cache。这意味着如果你用 4 卡跑一个 70B 模型并且模型有 80 层、每层 8 个 KV 头那么 KV Cache 会被切成 4 份每张卡存 20 层的所有 KV 缓存流水线并行或者 80 层的部分 KV 头张量并行。实际部署中你需要给每张卡分别预留 KV Cache 空间不能简单认为整个模型的 KV Cache 都放在一张卡上。在多卡推理服务里KV Cache 是分布在各卡上的这也给显存监控和故障排查增加了复杂度你看一张卡的显存快满了另一张还有余量就得检查并行切分和请求调度是不是均匀的。4. 云上部署开源模型从参数到命令的完整配置参考原理讲完这一节我结合自己的部署经验给你一套可以直接参考的配置方法和计算路径。我不会只扔一个启动命令完事每个关键参数背后的逻辑都会说清楚。4.1 第一步选实例、估显存总预算云厂商部署开源模型第一步永远是算显存总预算。你选择一个 GPU 实例本质就是选择了显存天花板。比如 A100 80GB、A10 24GB、L40S 48GB这几个是国产云上常见的推理卡。选卡的逻辑很简单模型权重 KV Cache 峰值 激活值缓冲这三项必须小于实例可用显存。以前面提到的 Qwen2.5-14B-Instruct 为例FP16 权重约 28GB如果希望支持至少 32K 上下文按它 GQA 4 个 KV 头计算每 token 的 KV 占用约 64KB假设平均每个并发请求实际上下文 16K token一个请求的 KV Cache 就占约 1GB。如果目标并发数是 32那 KV Cache 池需要约 32GB。加上模型权重总共约 60GB一张 80GB 的 A100 可以照顾但 48GB 的 L40S 就非常紧张只能降低并发目标或者把上下文缩短。这里有个经验想把并发提上去优先看 KV Cache而不是堆算力。同样一张卡模型换来换去只要权重和 KV 占用降下来并发就上去了。4.2 第二步使用 vLLM 启动服务并配置 KV Cache 相关参数以 vLLM 0.6 以上版本为例一个比较典型的启动命令类似这样python -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-14B-Instruct \ --gpu-memory-utilization 0.9 \ --max-model-len 32768 \ --max-num-seqs 64 \ --enable-prefix-caching \ --tensor-parallel-size 1 \ --kv-cache-dtype fp8 \ --dtype bfloat16这些参数拆开看每个都对应着显存管理的决策gpu-memory-utilization 0.9 表示给 KV Cache 池留尽可能多的空间。生产环境里我一般不设到 0.95 以上因为过高会挤压 CUDA graph 和激活值缓冲一旦出现显存抖动就会 OOM。max-model-len 是模型服务支持的最大上下文长度。这个值必须在你显存预算内否则 KV Cache 池根本放不下。max-num-seqs 是最大并发请求数。它和 max-model-len 一起决定了 KV Cache 池的“容量上限”计算公式大致是 max-num-seqs × max-model-len × 每tokenKV占用。如果发现启动时报 KV Cache 空间不足就把这两个值调低。enable-prefix-caching 开启前缀缓存复用。tensor-parallel-size 是多卡并行度。如果你用两张 A100就设 2它会自动切分模型和各头 KV。KV Cache 池的大小可以通过日志看到。服务启动时 vLLM 会打印类似 “KV cache size: 42.00 GiB” 的信息这时你就能确认三个关键数字模型权重多少、KV Cache 池多少、还剩多少给激活值。4.3 第三步用量化给 KV Cache 减负KV Cache 量化是最近特别热门的优化手段。思路和模型权重量化类似但对象是 Key、Value 向量。KV Cache 用 FP8 存储相对 FP16 直接省一半显存用 INT8 也是省一半INT4 极端一些能省 75%但精度损失和实现复杂度都会明显上升。vLLM 支持通过 kv-cache-dtype 参数指定缓存精度比如 4.2 节里我写了 fp8。FP8 在多数场景下精度损失非常轻微对生成质量影响几乎可以忽略我当时压测 Qwen 系列模型FP8 KV Cache 和 FP16 的输出结果在困惑度perplexity上差距在 1% 以内但 KV Cache 容量翻倍。如果你用的是支持 FP8 的新型 GPU比如 H100、L40S、Ada 架构卡这个参数基本可以放心开。还有一个思路是选模型时就选 GQA 架构的。GQA 把 KV 头数大幅减少KV Cache 占用呈线性下降。同样支持 128K 上下文的模型用了 GQA 的比没用 GQA 的省好几倍显存。这也解释了为什么现在的开源模型几乎都在往 GQA 靠。4.4 第四步接入 API 网关和 Kubernetes 调度云厂商部署不会只有一台机器。通常会在 Kubernetes 里跑 vLLM 的 Pod前面挂一个 API 网关做鉴权、限流、路由。这一步跟 KV Cache 有什么关系关系很大。Kubernetes 调度 GPU 时如果 Pod 重启或者漂移到另一台机器模型要重新加载KV Cache 全部清空所有请求都要从零开始 prefill。所以线上会通过“工作负载反亲和性”或者 GPU 节点池尽量把服务实例固定在某些节点上减少频繁重启。网关层也可以配置目标服务节点优先级让同一个会话的请求始终调度到同一个 vLLM 实例这样前缀缓存和多轮对话缓存才能命中。如果你在网关和服务的中间层加了负载均衡但没做会话亲和性sticky session同一个用户的分片请求可能打到不同实例。这样每个实例的 KV Cache 都无法被复用显存被白白浪费而且用户体感明显变慢。这个坑我踩过后来在网关层给每个会话分配固定的上游实例缓存命中率才稳定下来。5. 缓存命中率、过期与并发线上必踩的四个问题理论都讲完了接下来是真正决定服务稳定性的部分。这一节我会讲线上最典型的四个问题每个都给出定位思路和解决方案。5.1 问题一缓存命中率低prefill 开销大现象是服务整体延迟高、吞吐上不去CPU 和 GPU 利用率看起来都不高但日志显示大量请求在做整段 prefill。这时你要检查的是请求之间的公共前缀到底有多少。如果是缺乏系统提示词复用导致命中率低打开 enable-prefix-caching 基本能解决大半。如果这个参数原本就开着命中率还是低那就要看请求的输入是否规整。比如客户端把用户头像、签名、时间戳等动态信息塞进了 prompt 的开头导致每个请求的 prefix 都不一样缓存就完全无法复用。最佳实践是把静态的 system prompt 放在最前面动态信息靠后拼接让每个请求的公共前缀尽可能长。还有一种办法是客户端做 prompt 压缩把历史上文摘要化减少重复的较长文本输入。缓存命中率的监控指标vLLM 会在 Prometheus metrics 里暴露 prefix-cache-hit-rate 之类字段。我一般建议把它作为一个核心业务指标来盯命中率低于 40% 就要考虑调整 prompt 结构和会话亲和策略。前缀缓存的实现还和哈希粒度有关。vLLM 默认是把 token 序列哈希后有重叠地切块大多数情况下你不需要调内部细节但要注意如果你在网关层做了 prompt 改写或者模板渲染导致文本字符串变化就算内容逻辑一样哈希也不匹配缓存照样失效。5.2 问题二长时间挂起的会话导致缓存被清恢复时耗费大涨这是热词里“为什么一个会话等待几个小时之后耗费会大涨”直接对应的场景。用户把会话挂起几小时甚至隔夜期间新的请求把老会话的 KV Cache 挤出了显存池。当用户回来继续发言服务端发现没有缓存只能把他之前所有的对话历史从头做一次 prefill。如果历史有上万 token这次 prefill 就是一次肉眼可见的“卡顿”算力账单也随之跳动。要解决这个问题不是简单地把空闲会话的 KV Cache 一直留在显存里。因为长时间挂起的高上下文会话会占住大量显存直接影响其他活跃用户的服务质量。所以实现上通常做两层处理第一层是控制空闲超时时间比如连续 30 分钟没有新请求就把该会话的 KV Cache 释放但同时在服务端保存一份 prompt 历史等用户回来时重新 prefill第二层是把“重新 prefill”的开销尽量摊薄比如提前对历史做摘要压缩把历史中的关键信息提炼出来放到 System Prompt 里避免从原始长文本重新计算。如果你在云上做的是商业化 API 服务建议把“恢复会话”的逻辑主动告诉用户不要在两端都保留超长上下文客户端可以自己做一轮摘要把摘要传给服务端这样服务端只重新 prefill 摘要部分KV Cache 占用和恢复耗时都能大幅下降。这也是私有化部署里很讨巧的优化手段。5.3 问题三并发升高后 OOM服务频繁重启OOM 通常发生在两个阶段。一是启动阶段模型权重加上 KV Cache 池预留超过了显存总量vLLM 启动时报错二是运行阶段配置的 max-num-seqs 或者 max-model-len 偏大高并发请求把 KV Cache 池耗尽触发了 OOM 或请求排队严重。排查启动阶段的 OOM先看 vLLM 日志里打印的模型权重大小、KV Cache 大小和可用显存。如果模型权重 30GB、KV Cache 预留 50GB但实际只有 72GB 可用那就需要调低 gpu-memory-utilization 或 max-num-seqs。运行阶段的 OOM要先看监控里的并发请求数和 KV Cache 池剩余空间如果剩余空间经常接近 0说明两个选择要么降低并发限额给每个请求留出更充足的空间要么升级显存更大的实例或者开启 KV Cache 量化。有一个实用的检查公式单实例最大 KV Cache 需求 max-num-seqs × max-model-len × 每 token KV 占用。启动前拿这个值和“可用显存 - 模型权重 - 激活缓冲”对比就能提前判断是否会 OOM。别忘了把 batching 调度中的并发请求数量也纳进来因为 continuous batching 会动态插入新请求瞬时请求数可能超过预设 max-num-seqs超出部分会排队但不应该把缓存池撑爆。5.4 问题四分布式缓存与 KV Cache 的区别很多人听到“缓存”就联想到 Redis 和分布式缓存容易把 KV Cache 跟它们混淆。这里我明确区分一下KV Cache 是 GPU 显存里按请求粒度的注意力中间结果生命周期极短通常只有几秒到几小时不可能持久化解码到磁盘上Redis 之类的分布式缓存存的是业务数据或模型服务结果作用在应用层。KV Cache 的“分布式”体现在多卡和多实例并行时缓存按层和按头被切分到不同算力单元上而不是简单地把一份数据复制到多个节点。所以你千万不要把 KV Cache 用到 Redis 层面去解决。线上架构应该是Redis 可以做结果缓存和会话历史缓存KV Cache 只活在推理实例内部。两者结合才能把“有状态的会话”和“无状态的负载均衡”统一起来会话历史放 RedisKV Cache 放推理实例网关根据会话 ID 把请求路由到固定实例这样命中率和服务稳定性都最好。6. 实际部署复盘一套可复制的云上 KV Cache 调优流程前面讲了大量理论最后我按自己的实际经验把一套完整的部署和调优流程复盘给你。这套流程没有绑定具体云厂商任何有 GPU 实例的环境都能照做。6.1 从选型到上线的七天流程我见过很多团队一上来就调参数结果压测数据忽高忽低根本看不出瓶颈。正确顺序应该是这样先定模型和并发目标再算显存账然后小成本试跑压测拿到真实数据后再做量化优化最后才上生产。第一天做的事是确定模型版本、量化方式和目标并发数。比如目标是跑 Qwen2.5-14B-Instruct、并发 32、平均每请求上下文 16K token。按之前算的每 token 64KB一个请求占 1GB32 并发就需要 32GB KV Cache模型权重按 FP8 算 14GB总共需要约 46GB再加激活和 CUDA 缓冲选择 80GB A100 没问题48GB 的 L40S 比较紧张。第二天到第四天做试跑。先把 gpu-memory-utilization 拉到 0.9跑 1000 个真实请求样例统计单请求延迟、并发请求量、KV Cache 池剩余空间。这里我特别提醒压测数据要看 P95 延迟不能只看平均值。平均值容易被少量短请求拉低P95 才能体现长上下文请求的真实体感。第五天到第六天做优化。如果 KV Cache 池剩余空间大但 P95 延迟高说明瓶颈不在显存而在计算可以考虑增大 batch size 或换成更强算力的卡如果 KV Cache 池经常满且排队严重优先开 KV Cache 量化或缩短 max-model-len如果请求间的公共前缀明显打开前缀缓存并确认网关有会话亲和。第七天上生产前的最后一步是把监控配齐。我至少要盯四个指标GPU 显存使用率、KV Cache 池剩余空间、前缀缓存命中率、每个请求的平均 prompt token 数。这四个指标能帮你快速定位是容量问题、调度问题还是请求结构问题。6.2 一组压测数据供参考我自己在 A100 40GB 上跑过 Qwen2.5-7B-Instruct精度 BF16权重约 15GBKV Cache 池大约 20GB。关闭前缀缓存、32 并发、输入输出平均 2K token 时吞吐约 1800 token/sP95 首 token 延迟约 1.2 秒。开启前缀缓存后因为有大量请求复用了 2K token 的公共 system prompt吞吐提升到约 2400 token/s首 token 延迟降到 0.7 秒左右。再把 KV Cache 改成 FP8官方文档和数据实验显示显存占用大约减半我实测并发上限可以压到 48 左右吞吐还能再涨一截。6.3 一点心得KV Cache 优化是系统工程我接触过不少朋友以为 KV Cache 优化就是加一个参数的事实际做下来会发现它同时涉及模型选型、显存规划、调度策略、网关路由、prompt 设计五个层面。比如模型本身值不值得量化、请求的 prompt 结构合理不合理、网关能不能做到会话亲和这些因素单独拎出来哪个都会影响 KV Cache 的实际利用率。我个人的做法是把 KV Cache 相关的参数写进部署配置模板里每次换模型、换实例时先跑一遍模板里的压测脚本再根据输出决定要不要调整。千万不要因为某个模型很火就直接抄别人的启动命令不同模型的层数、KV 头数、上下文长度差太多了参数必须自己算一遍才靠谱。最后分享一个小技巧如果你用的是带前缀缓存能力的推理框架并且业务允许尽量把 system prompt 固定下来不要频繁改动。因为 system prompt 一变前缀缓存里所有以旧 system prompt 开头的 KV 块全部无法复用相当于一次缓存全量失效。这个影响在生产环境特别明显我见过有团队改了一版 system prompt 之后线上延迟瞬间翻倍最后发现是前缀缓存命中率从 70% 掉到了接近 0。把 system prompt 当成接口协议的一部分来管理版本化、向下兼容才能让缓存的价值真正稳定释放。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。