1. 显存账本24 GiB 到底能装下什么先把结论摆在前面24 GiB 显存跑四路 32K 上下文的 Qwen2.5能不能装下取决于你选的是哪个尺寸的模型以及 KV Cache 用什么精度存。这不是一个能或不能的二选一问题而是一道算术题。我见过太多人上来就问24G 能不能跑 32K然后被一句看情况打发走其实这个情况是可以精确算出来的。1.1 显存被谁吃掉了一张 24 GiB 的卡比如 4090、3090、L4 这类显存开销大致分四块模型权重这是死账加载完就固定占着跟上下文长度无关。KV Cache这是活账随并发数和上下文长度线性增长也是本文的主角。激活值与临时缓冲前向计算时的中间张量跟 batch size 和序列长度相关通常几百 MB 到 1 GB 量级。框架开销CUDA context、通信缓冲、显存碎片等vLLM 这类框架一般预留 1~2 GiB。很多人算显存只算权重结果一上并发就 OOM问题就出在 KV Cache 这块活账上。权重是房租KV Cache 是水电费房租固定水电费按用量走你开四路 32K等于四台空调同时开满。1.2 权重这一项Qwen2.5 各尺寸的占用Qwen2.5 是个系列从 0.5B 到 72B 都有。我们按常见的几个尺寸用 FP16/BF162 字节和 INT4 量化约 0.5 字节含量化开销实际按 0.55 估分别算权重占用模型尺寸参数量BF16 权重INT4 权重估24G 是否放得下Qwen2.5-0.5B0.5B~1.0 GiB~0.3 GiB轻松Qwen2.5-1.5B1.5B~3.0 GiB~0.9 GiB轻松Qwen2.5-3B3B~6.0 GiB~1.8 GiB轻松Qwen2.5-7B7B~14.0 GiB~4.2 GiBBF16 勉强INT4 宽裕Qwen2.5-14B14B~28.0 GiB~8.4 GiBBF16 放不下INT4 可以Qwen2.5-32B32B~64.0 GiB~19.2 GiB只有 INT4 勉强这张表是后面所有推算的基础。注意 BF16 权重按参数量 × 2 字节算7B 就是 7 × 2 14 GiB这是纯权重还没算任何缓存。所以标题里权重装进了 24 GiB这句话本身就限定了模型尺寸——7B 的 BF16 权重 14 GiB 是能装进 24 GiB 的14B 的 BF16 就装不下了。这是第一个分水岭。1.3 为什么 KV Cache 是决定性的权重是固定的KV Cache 是弹性的所以真正决定四路 32K 装不装得下的是 KV Cache 的算法。KV Cache 的本质是Transformer 在自回归生成时每个 token 的 Key 和 Value 都要缓存下来避免重复计算。序列越长缓存越大并发越多缓存份数越多。它的计算公式是KV Cache 大小 2 × 层数 × KV头数 × 头维度 × 序列长度 × 并发数 × 精度字节数其中 2 代表 Key 和 Value 两份层数、KV 头数、头维度是模型结构决定的序列长度和并发数是你的业务决定的精度字节数是你能调的。这个公式后面会反复用到建议先记住。2. KV Cache 的精确计算四路 32K 到底要多少现在进入正题。我们以 Qwen2.5-7B 为例因为它是 24 GiB 卡上最现实的 BF16 选择。先看它的结构参数。2.1 Qwen2.5-7B 的结构参数Qwen2.5-7B 的关键结构基于公开模型配置的常见值层数num_hidden_layers28注意力头数num_attention_heads28KV 头数num_key_value_heads4这是 GQA分组查询注意力头维度head_dim128隐藏维度3584这里有个关键点Qwen2.5-7B 用的是 GQAKV 头数只有 4而不是 28。这是它能省显存的根本原因。如果是传统的 MHAKV 头数等于注意力头数 28KV Cache 会大 7 倍四路 32K 根本别想。GQA 让 KV 头数从 28 降到 4直接砍掉 85% 的 KV 开销这是现代大模型能长上下文部署的核心设计之一。2.2 单路 32K 的 KV Cache 计算套公式单路 32K32768 token的 KV Cache每 token 每层的 KV 大小 2 × KV头数 × 头维度 × 精度字节 2 × 4 × 128 × 2BF16 2048 字节 2 KiB再乘以层数和序列长度单路 32K KV 2 KiB × 28 层 × 32768 token 2 × 28 × 32768 KiB 1,835,008 KiB ≈ 1.75 GiB所以单路 32K 的 KV Cache 约 1.75 GiB。这个数字很关键记住它。2.3 四路 32K 的总账四路并发每路 32K四路 KV 1.75 GiB × 4 7.0 GiB现在把账合起来Qwen2.5-7BBF16 权重项目占用模型权重BF16~14.0 GiBKV Cache4 × 32KBF16~7.0 GiB激活与临时缓冲~0.5 GiB框架开销~1.5 GiB合计~23.0 GiB23.0 GiB卡在 24 GiB 的边上。理论上装得下实际上非常危险。因为显存碎片、CUDA context 实际占用、vLLM 的 block 管理粒度通常按 16 个 token 一块分配会有浪费实际占用往往比理论值高 5%~10%。23 GiB 的理论值实际很可能冲到 24.5 GiB 以上直接 OOM。所以我的判断是Qwen2.5-7B BF16 四路 32K BF16 KV Cache在 24 GiB 卡上属于纸面能过、实测悬的状态不建议直接上生产。2.4 那怎么办三个可行的调整方向既然卡在边上就得做取舍。有三条路第一条降 KV Cache 精度。把 KV Cache 从 BF16 降到 FP8KV 占用直接减半从 7.0 GiB 降到 3.5 GiB。总账变成 14 3.5 0.5 1.5 19.5 GiB宽裕多了。FP8 的 KV Cache 对生成质量的影响在多数任务上几乎感知不到这是性价比最高的一招。第二条降权重精度。用 INT4/AWQ/GPTQ 量化权重7B 权重从 14 GiB 降到约 4.2 GiB。总账变成 4.2 7.0 0.5 1.5 13.2 GiB四路 32K 轻松装下甚至还能再开几路。代价是量化会带来一定的质量损失需要评估你的任务能不能接受。第三条降并发或降上下文。如果业务上四路不是硬需求两路 32K 的 KV 只有 3.5 GiB总账 14 3.5 0.5 1.5 19.5 GiB也能过。或者保持四路但上下文降到 16KKV 减半到 3.5 GiB同样能过。方案权重KV Cache总占用可行性7B BF16 4×32K BF1614.07.0~23.0悬7B BF16 4×32K FP814.03.5~19.5稳7B INT4 4×32K BF164.27.0~13.2很稳7B BF16 2×32K BF1614.03.5~19.5稳7B BF16 4×16K BF1614.03.5~19.5稳这张表基本就是这道题的答案。如果你问我推荐哪个我会选 FP8 KV Cache因为它对质量影响最小改动成本也最低。3. vLLM 里怎么把这些参数落地算清楚了账接下来是怎么在 vLLM 里把它配出来。vLLM 是目前部署这类模型最常用的推理框架它的显存管理核心是 PagedAttention把 KV Cache 切成固定大小的 block 来管理这也是它能高效利用显存的原因。3.1 关键启动参数逐个说一个典型的 vLLM 启动命令长这样vllm serve Qwen/Qwen2.5-7B-Instruct \ --max-model-len 32768 \ --gpu-memory-utilization 0.92 \ --max-num-seqs 4 \ --kv-cache-dtype fp8 \ --tensor-parallel-size 1 \ --port 8000逐个解释这些参数为什么这么设--max-model-len 32768单条请求的最大上下文长度设成 32K。这个值直接决定单路 KV 的上限设大了浪费设小了截断。--gpu-memory-utilization 0.92vLLM 允许占用的显存比例。默认 0.9我一般设 0.92~0.95。设太高容易和系统其他进程抢显存设太低浪费。24 GiB 卡上 0.92 大约留 2 GiB 给系统和碎片。--max-num-seqs 4最大并发序列数这就是四路的来源。vLLM 会按这个值预留 KV Cache 空间。--kv-cache-dtype fp8KV Cache 用 FP8 存这是省显存的关键开关。注意不是所有卡都支持 FP8需要确认你的 GPU 架构Ada、Hopper 及更新的一般支持。--tensor-parallel-size 1单卡不切分。3.2 gpu-memory-utilization 到底怎么定这个参数是新手最容易踩坑的地方。它的含义是vLLM 最多用掉多少比例的显存vLLM 会先加载权重然后把剩余显存按这个比例拿来做 KV Cache。假设 24 GiB 卡权重占 14 GiB系统和其他占 2 GiB剩 8 GiB。如果gpu-memory-utilization设 0.92vLLM 认为自己能用 24 × 0.92 22.08 GiB减去权重 14 GiB剩 8.08 GiB 给 KV Cache 和激活。四路 32K 的 KV 需要 7 GiBBF16或 3.5 GiBFP8FP8 下 8.08 GiB 是够的BF16 下就非常紧。提示gpu-memory-utilization不是越高越好。设 0.95 以上时如果系统里有其他进程比如监控、日志也在用显存很容易触发 OOM。我一般留 5%~8% 的余量。3.3 怎么确认 KV Cache 实际分了多少vLLM 启动时会在日志里打印 KV Cache 的分配情况类似INFO: GPU KV cache size: 262,144 tokens INFO: Maximum concurrency for 32,768 tokens per request: 8.00x这行日志极其重要。Maximum concurrency就是在 32K 上下文下最多能同时跑几路。如果它显示 8.00x说明你的显存能支持 8 路 32K四路绰绰有余如果显示 2.00x那四路就会排队甚至拒绝。我每次部署完第一件事就是看这行日志。它比任何理论计算都准因为它是 vLLM 根据实际可用显存算出来的。如果这个值小于你的目标并发就得回去调参数——降 KV 精度、降权重精度、或者降max-model-len。3.4 一个容易忽略的坑block 粒度浪费vLLM 的 PagedAttention 按 block 分配 KV Cache默认 block size 是 16 个 token。这意味着即使你只用了 1 个 token也会占一个 block16 token 的空间。对于长上下文这个浪费可以忽略但对于大量短请求浪费会累积。如果你的场景是少量长请求 大量短请求混合可以考虑调--block-size但一般不建议动默认值在多数场景下是最优的。真正要关注的是max-num-seqs和max-model-len的乘积——它决定了 KV Cache 的峰值需求。4. 实测踩坑与排查实录理论算得再漂亮实测总会给你惊喜。下面是我在实际部署中遇到过的几个典型问题以及排查思路。4.1 启动就 OOM权重都加载不进去现象vLLM 启动时直接报torch.cuda.OutOfMemoryError连权重都没加载完。原因多半是模型尺寸选错了。比如在 24 GiB 卡上加载 Qwen2.5-14B 的 BF16 权重28 GiB必然 OOM。排查先确认模型权重的实际大小。看模型目录下*.safetensors文件的总大小或者用du -sh看。BF16 权重约等于参数量 × 2 字节7B 约 14 GiB14B 约 28 GiB。解决换更小的模型或者用量化版本GPTQ/AWQ/INT4。24 GiB 卡上BF16 最多到 7BINT4 可以到 14B。4.2 启动成功但一请求就 OOM现象服务起来了日志显示 KV Cache 也分了但一发长请求就 OOM。原因max-model-len设得比实际 KV Cache 能支撑的长。比如你设了 32K但显存只够分 20K 的 KV请求一超过 20K 就崩。排查看启动日志里的Maximum concurrency for 32768 tokens per request。如果这个值小于 1说明单路 32K 都跑不了。解决降max-model-len或者降 KV 精度或者降权重精度。三者选其一或组合。4.3 并发上不去请求排队严重现象服务不崩但请求响应很慢日志里Running: 4, Waiting: 20大量请求在排队。原因max-num-seqs设小了或者 KV Cache 不够支撑更多并发。vLLM 的调度器scheduler会优先跑能放进 KV Cache 的请求放不下的就排队。排查看日志里的Running和Waiting数量。如果Waiting持续很高说明并发能力不足。解决如果显存还有余量调大max-num-seqs如果显存不够降 KV 精度或权重精度来腾空间。注意max-num-seqs调大后KV Cache 需求也线性增长要重新算账。4.4 FP8 KV Cache 开了但没生效现象设了--kv-cache-dtype fp8但显存占用没降。原因可能是 GPU 不支持 FP8vLLM 静默回退到了 FP16/BF16。或者参数名写错了不同 vLLM 版本参数名可能有差异。排查看启动日志里有没有Using FP8 KV cache之类的提示。如果没有就是没生效。解决确认 GPU 架构支持 FP8Ada/Hopper 及更新。如果不支持只能走量化权重这条路。4.5 常见问题速查表现象可能原因排查方法解决启动即 OOM权重太大看权重文件大小换小模型或量化请求即 OOMmax-model-len 过大看 KV Cache 日志降上下文或降精度并发上不去max-num-seqs 小或 KV 不足看 Running/Waiting调大并发或降精度FP8 没生效GPU 不支持或参数错看启动日志确认架构或改量化显存碎片多长时间运行看显存占用曲线定期重启或调 block-size注意vLLM 的版本差异比较大参数名和默认值在不同版本间可能变化。部署前一定先看对应版本的文档别照搬旧教程。我踩过好几次参数名对了但版本不认的坑。5. 几个延伸思考不只是 7B 和 32K这道题的本质是显存预算分配模型和上下文只是变量。把这套算法吃透你可以套用到任何组合上。5.1 换模型怎么算换任何模型只要拿到四个数层数、KV 头数、头维度、精度就能算 KV Cache。比如 Qwen2.5-14B层数 48KV 头数 8头维度 128单路 32K 的 KV 就是2 × 8 × 128 × 2 字节 × 48 层 × 32768 token 2 × 8 × 128 × 2 × 48 × 32768 字节 ≈ 6.4 GiB四路就是 25.6 GiB光 KV 就超过 24 GiB 了所以 14B 在 24 GiB 卡上跑四路 32KBF16 权重下完全不可能必须量化权重 FP8 KV。5.2 换精度怎么算KV Cache 精度从 BF16 到 FP8占用减半到 INT8也减半到 INT4减到四分之一。但精度越低生成质量损失越大。FP8 是目前性价比最高的选择INT4 KV 在多数任务上已经开始能感知到质量下降了。5.3 换硬件怎么算如果是 48 GiB 卡比如 A6000、L40S预算翻倍7B BF16 四路 32K BF16 就非常宽裕了甚至能上 14B。如果是 80 GiB 卡A100/H10014B BF16 四路 32K 也没问题。显存预算翻倍能玩的组合就多一个数量级。5.4 一个反直觉的点并发不是越多越好很多人觉得并发越高吞吐越大其实不然。当 KV Cache 接近显存上限时vLLM 的调度器会频繁做 block 的换入换出反而拖慢整体吞吐。找到显存刚好用满但不溢出的并发数才是吞吐最优点。这个点通常比理论最大并发略低一点需要实测调。我在实际部署中的体会是与其纠结四路 32K 到底装不装得下不如先把 KV Cache 的账算清楚然后根据业务对质量、并发、上下文长度的优先级做取舍。多数情况下FP8 KV Cache 是那个既省显存又不太伤质量的甜点选项值得优先试。最后分享一个小技巧部署完先别急着压测用nvidia-smi盯着显存曲线跑几轮真实请求看峰值占用和稳态占用差多少这个差值就是你真正的安全余量。