vLLM KV cache 与并发计算器

vLLM 把 --gpu-memory-utilization 允许的显存扣掉权重和预热试运行后剩下的部分全部给 KV cache,再按 16 个 token 一块切分。选择模型、GPU 和参数,就能看到它启动时会打印的缓存池大小、你的上下文长度下能同时处理多少请求,以及 vllm serve 命令。

– 个 token 的 KV cache(GPU KV cache size)

每张 GPU 的权重
–
预留:激活值、CUDA graph、非 torch 内存
–
每张 GPU 的 KV cache 显存
–
每个 token 的 KV cache(每张 GPU)
–
最大上下文下的最大并发
–
平均长度下能同时处理的请求
–

启动命令

vLLM 启动时应该打印的日志

与 vLLM 日志对照

每一行都是 GitHub issue 里公开的 vLLM 启动日志。“按日志显存计算”用日志打印的 Available KV cache memory 和本页的公式算出缓存池,检验每个 token 的字节数、分组和按块取整;“完全由我们估算”只用 GPU、设置和本页的预留估计,不看日志里的任何数字。v0.24.0 之前,混合注意力模型的日志打印的是块数 ÷ 组数 × 16,表中这些行按当时的格式比较。

日志 模型 GPU 与设置 日志中的 KV 显存 日志中的缓存池 按日志显存计算 完全由我们估算
#42593 Llama 3.1 8B H100 80GB HBM3,TP 1,util 0.9,auto KV,131,072 token,vLLM 0.14.1 51.39 GiB 420,944 420,976 +0.01% 432,048 +2.6%,52.74 GiB
#27604 Llama 3.1 8B H100 80GB HBM3,TP 1,util 0.9,fp8 KV,131,072 token,vLLM 0.11.0 54.32 GiB 890,000 889,968 0.00% 864,112 −2.9%,52.74 GiB
#38107 Qwen3 8B 2 × Radeon PRO W6800 32GB(ROCm),TP 2,util 0.9,auto KV,32,768 token,vLLM 0.1.dev15181 (2026-03) 20.23 GiB 294,624 294,608 −0.01% 280,592 −4.8%,19.27 GiB
#26480 gpt-oss-120b 2 × A100 80GB PCIe,TP 2,util 0.85,auto KV,131,072 token,vLLM 0.11.0 31.78 GiB 925,696 925,648 −0.01% 977,808 +5.6%,33.57 GiB
#36849 gpt-oss-20b 2 × RTX 5090,TP 2,util 0.9,fp8 KV,100,000 token,vLLM 0.17.1 16.62 GiB 1,452,000 1,452,272 +0.02% 1,525,536 +5.1%,17.46 GiB
#58580 Gemma 4 26B-A4B H200,TP 1,util 0.9,auto KV,131,072 token,vLLM 0.28.0 73.43 GiB 1,652,749 1,652,749 0.00% 1,671,267 +1.1%,74.25 GiB

#26480:A100 没有原生 MXFP4 kernel,vLLM 会重新打包专家权重,所以权重比我们的估算多 6%。

#36849:这次运行设置了 --max-num-batched-tokens 98304,是常见值的 12 倍,所以激活值预留很大。

#58580:权重里包括这次运行加载的 MTP 草稿模型(gemma-4-26B-A4B-it-assistant),它的草稿层复用主模型的缓存。日志还列出了其余部分:非 torch 内存 1.17 GiB、峰值激活值 1.89 GiB、CUDA graph 0.16 GiB。

vLLM 如何确定 KV cache 大小

以下公式来自 vLLM main 分支(ac7f3e11,与 v0.30.0 相同),检查于 。

  1. 可用显存(gpu_worker.py):每张 GPU 上,总显存 × gpu_memory_utilization,减去权重、一次 max_num_batched_tokens 规模的试运行中激活值的峰值、非 torch 内存(CUDA 上下文、NCCL)以及 CUDA graph 的估算值(v0.20 起默认扣除)。剩下的就是日志里的 Available KV cache memory。默认利用率从 v0.20.0 起是 0.92,之前是 0.9。
  2. 页(kv_cache_interface.py):一层的一个块 = 16 个 token × 每张 GPU 的 KV 头数 × (K 维 + V 维) × 每个值的字节数。张量并行时 KV 头平分到各卡,KV 头数少于卡数时每张卡保留 1 个头(复制)。MLA 每个 token 只存一个潜向量,每张卡都存完整的一份。
  3. 块数:块数 = 可用显存 ÷ 每块字节数(向下取整)。只有一种注意力的模型把所有层放在一组;滑动窗口和全注意力混合的模型按相同层数分组,页大小不同时给较小的页更长的块(Gemma 4 的 512 维全局层用 32 个 token 一块)。
  4. 容量:每个请求需要的块数是各组之和:全注意力层按 max_model_len,滑动窗口层最多 窗口 − 1 + 2 × max_num_batched_tokens 个 token(异步调度默认同时有两个批次在途),再加 1 块。最大并发 = 块数 ÷ 每个请求的块数;日志里的 GPU KV cache size = 最大并发 × max_model_len。

第 1 步中除权重外的部分无法在浏览器里测出,所以本页按 vLLM 在该显卡上默认的 max_num_batched_tokens 取一个经验值:2,048 时约 1.5 GB(0.4–2.5),8,192 时约 3.5 GB(2–5),16,384 时约 4 GB(2.5–6),依据是上表的日志。开启前缀缓存不会改变缓存池大小,但命中的请求会共享块,所以实际并发可能更高。

单个请求的显存和能装下的显卡见 LLM 显存计算器,生成速度见 LLM 速度计算器。

使用方法

  1. 选择模型,或加载任意 Hugging Face 模型 id,再选择 GPU 型号和数量(张量并行)。
  2. 设置 --gpu-memory-utilization、权重精度和 KV cache 类型。
  3. 设置 --max-model-len 和每个请求的平均 token 数(提示词加输出)。
  4. 查看缓存池、并发数和命令。如果你已经有启动日志,可以把其中的“Available KV cache memory”和这里的估算对照。

常见问题

vLLM 如何决定 KV cache 的大小?

启动时它先加载权重,用 max_num_batched_tokens 个 token 跑一次前向传播,测出激活值的峰值,并估算 CUDA graph 占用的显存。KV cache 得到的是:GPU 总显存 × --gpu-memory-utilization,减去权重、这个峰值和 PyTorch 之外的显存(CUDA 上下文、NCCL),再按 16 个 token 一块切分。Qwen3 8B 在一张 H100 上用默认设置时约为 54.0 GB,即 393,392 个 token。

启动日志里的“GPU KV cache size”和“Maximum concurrency”是什么意思?

前者是缓存池能容纳多少个 token 的上下文;后者是长度正好为 --max-model-len 的请求能同时放下几个(Qwen3 8B 在 H100 上、32,768 时为 12.01x)。实际请求通常更短:每个 4,096 个 token 时,同一个缓存池能同时处理约 96 个。vLLM 不会拒绝多出的请求,而是让它们排队,或在块用完时抢占正在运行的请求。

加一张 GPU,KV cache 会翻倍吗?

权重较大时不止翻倍。使用 --tensor-parallel-size 2 时,每张 GPU 只保存一半权重和一半 KV 头。Llama 3.1 70B 以 FP8 在一张 H100 上只剩 3.6 GB 给缓存,即 11,696 个 token,连一个 32K 请求都放不下;在两张 H100 上每张剩 36.4 GB,缓存池可容纳 238,720 个 token(32K 时并发 7.29x)。KV 头数少于 GPU 数时,每张卡都要保留一个完整的头,每个 token 的缓存就不再减少。

要不要用 --kv-cache-dtype fp8?

它把每个 token 的字节数减半,缓存池能容纳的 token 数翻倍:Qwen3 8B 在 H100 上从 393,392 增加到 786,784。质量损失通常不大,但取决于模型和注意力后端,最好在自己的任务上验证。

为什么 vLLM 报告的 gpt-oss 和 Gemma token 数比按每 token 字节数算的少?

它们混合了滑动窗口层和全注意力层。vLLM 为滑动窗口层给每个请求预留“窗口 − 1 + 两个在途批次的 token”(开启异步调度时为 2 × max_num_batched_tokens)再加 1 块;而且从 v0.24 起,日志里的 token 数是“最大并发 × --max-model-len”,把每个层组占用的块都算进去。gpt-oss-120b 在一张 H100 上、131,072 个 token 时约有 4.9 GB 留给缓存,即 125,885 个 token,放一个满长度请求处于临界状态。

为什么我日志里的“Available KV cache memory”和这里不一样?

除权重外 vLLM 预留的部分(激活值峰值、CUDA graph、NCCL、CUDA 上下文)取决于版本、注意力后端、词表大小和 max_num_batched_tokens。本页使用 vLLM 默认批大小的 5 条公开日志中,这部分为 0.5–4.8 GB。有了自己的日志后,这一行就是准确值,缓存池可以直接由它算出:按日志中的显存计算,本页公式与每条日志的 token 数相差都在 0.02% 以内。

要不要调高 --gpu-memory-utilization?

它是这个 vLLM 实例可以使用的 GPU 总显存比例,包括权重:v0.20.0 起默认为 0.92,之前是 0.9。权重和激活值用剩的部分都会变成 KV cache,所以在 H100 上把它调到 0.95,Qwen3 8B 的缓存会多出 2.4 GB(从 393,392 增加到 410,672 个 token)。请给 GPU 上的其他程序留出余量,桌面或另一个进程都可能让 vLLM 启动失败。

我输入的内容会被上传吗?

不会。计算在你的浏览器中进行,唯一的网络请求是按 id 加载模型时访问 Hugging Face。

更多计算器

更新于