模型参数能放进显存,不代表还能接下任意数量的会话。长上下文、并发生成和运行时缓冲一起增长,往往先把“看起来还有空位”的容量计划推翻。
主机 Swap 与 GPU KV 缓存是两本账
2026年10月5日,Kubernetes 的 节点 Swap 工作负载分析讨论了主机内存分页与不同工作集的取舍。它并不意味着开了节点 Swap 就能扩充 GPU 上的 KV 缓存。框架可以提供显式 offload,但需要单独验证传输开销与延迟。
Transformers KV cache 文档介绍不同缓存策略及其内存取舍。具体占用受注意力结构、缓存精度、滑动窗口、分页、共享前缀和并行切分影响。不能只拿模型参数量乘一个常数,便宣布某张卡可承载多少 Agent。
图中公式计算所有活跃会话的 KV 总量;最终准入仍要扣除权重、激活、框架工作区及安全余量。会话数量也不是唯一控制量,输入长度与生成 token 上限同样重要。
用显式假设估一个上界
以下代码限定为常规注意力、各层缓存长度相同、K/V 同精度且未作量化或前缀共享的教学模型。kv_heads是 KV 头数,不一定等于 query 头数。
GiB = 1024 ** 3 def kv_bytes(tokens, layers, kv_heads, head_dim, bytes_per_value=2): values = (tokens, layers, kv_heads, head_dim, bytes_per_value) if any(type(v) is not int or v <= 0 for v in values): raise ValueError('positive integer dimensions required') return 2 * tokens * layers * kv_heads * head_dim * bytes_per_value budget = 24 * GiB weights, runtime, reserve = 12 * GiB, 3 * GiB, 3 * GiB per_session = kv_bytes(4096, layers=32, kv_heads=8, head_dim=128) available = budget - weights - runtime - reserve admission_limit = max(0, available // per_session) assert per_session == 512 * 1024 ** 2 assert admission_limit == 12 assert kv_bytes(8192, 32, 8, 128) == 2 * per_session print({'illustrative_session_limit': admission_limit})输出12只是这些假设下的算术结果,不能作为某张24 GiB显卡的实测承诺。运行时占用可能随 batch、图捕获和模型算子变化;预填充阶段的峰值也不一定出现在稳态采样点。
历史会话量可以帮助预测高峰需求,但预测不会改变单次请求的显存预算。先用实际观测校准每种长度组合,再决定预留与扩容;本文不把算式称为显存预测模型。
让排队承受不确定性
真实服务应记录已分配 KV 块、排队等待、拒绝率、首 token 延迟与生成吞吐,区分客户端放弃和服务端超时。对超长请求可以限制预算、单独排队或要求用户缩短上下文,但不能偷偷截断后仍声称完整回答。
调高准入前,先固定模型与推理框架版本,在目标硬件上测试长度组合和失败回收。本文只验证容量算式及维度校验,没有加载模型、占用 GPU 或验证 offload。把假设写进准入策略,比把显存不足包装成“弹性自愈”更容易排查。