Spots

权重装进了 24 GiB,四路 32K 上下文还装得下吗?

权重装进了 24 GiB,四路 32K 上下文还装得下吗? 模型权重已经加载,短问题也能回答,于是把服务目标改成四路长上下文。接下来遇到的却是缓存不足、请求等待,或者在某个峰值阶段显存不够。第一反应往往是:“权重才占一部分,剩下的显存为什么不够?” 加载成功只验证了当时那笔开销。生成中的历史信息也要留在 GPU 上,运行时还会需要临时空间。要判断四路长请求是否可行,需要回答的是:扣掉权重和非缓存峰值后,每张卡到底还有多少空间,能够同时保留多少 token 的 KV?

下面用 Qwen2.5-7B-Instruct 的公开配置算一笔账。24 GiB 显存、权重与运行开销都是明确设定的教学条件,没有加载该模型、运行 vLLM…

下面用 Qwen2.5-7B-Instruct 的公开配置算一笔账。24 GiB 显存、权重与运行开销都是明确设定的教学条件,没有加载该模型、运行 vLLM 或做 GPU 压测。算式用于排除不成立的容量承诺,不作为这款模型在某张显卡上的实测结果。 先固定单位:1 GB 是 10⁹ 字节,1 GiB 是 2³⁰ 字节。本文的 24 GiB 指假设运行时可见总量恰为 24 × 2³⁰ 字节,不是把任何厂商标称的“24 GB”直接代入。实际机器应读取字节数再换算。 “其他”包括该执行配置下的激活与临时工作区、图捕获等非权重开销,不能用空闲时截图代替峰值。若权重已经单列,其他项就不要再把同一权重算一遍。这里是分账方法,不是保证每项峰值会在相同时刻达到最大,也不是某个版本内部变量的逐一映射。 vLLM v0.28.0 的自动预算路径提供了直接证据。在 GPU Worker 源码中,KV 可用量的计算包含下面三项: 这是赋值表达式中的连续项,省略了外侧变量和括号,不能单独运行。它说明引擎会从请求的预算里扣除已分析的非 KV 开销及适用的 CUDA Graph 估算,而不是把权重加载后看见的全部空闲量直接交给缓存。vLLM GPU Worker 源码

现在设定:单卡 24 GiB,显式选择利用率参数 0.9,权重预算记为 15 GiB,其他非 KV 峰值预留

现在设定:单卡 24 GiB,显式选择利用率参数 0.9,权重预算记为 15 GiB,其他非 KV 峰值预留 2 GiB。后两项只是本例输入,不是 Qwen 官方公布或本文测得的占用;真实部署必须用当前精度、加载布局与执行配置重新测量。也没有用模型名里的“7B”乘两字节,冒充精确运行时权重。 预算外的 2.4 GiB 不再重复算作 KV 可用空间。本例也没有把它承诺为能抵挡任意峰值的安全保证。

这里的 0.9 是主动设定。核验时 v0.28.0 文档默认值为 0.92;gpu_memory_utilization…

这里的 0.9 是主动设定。核验时 v0.28.0 文档默认值为 0.92;gpu_memory_utilization 描述当前实例的预算比例,不是监控面板上的 GPU 忙碌百分比。另一个参数 kv_cache_memory_bytes 直接指定每 GPU的 KV 字节量;设置后会忽略前述比例的自动预算方式,不能把两者当成可叠加的额度。引擎参数说明 四路 32K,需要缓存的是 131,072 个 token KV Cache 保存后续生成还会使用的注意力 Key 和 Value。对普通全注意力、相同结构的各层,采用相同 K/V 维度和精度、不考虑共享时,可以从数据形状推导:

开头的 2 是 Key 与 Value。并发序列长度不同时,总 token 数应该逐条相加。它既不是本轮新计算的

开头的 2 是 Key 与 Value。并发序列长度不同时,总 token 数应该逐条相加。它既不是本轮新计算的 token 数,也不只是输入长度:已处理的 prompt 和生成历史都可能占缓存。队列里尚未获得 KV 的请求则不能按“已驻留”重复计入。

这四行从配置不同位置选取,非连续摘录。由此得到 head 维度 3584 ÷ 28 = 128;GQA

这四行从配置不同位置选取,非连续摘录。由此得到 head 维度 3584 ÷ 28 = 128;GQA 使用 4 个 KV heads,不能把 28 个 Query heads 代入 KV 公式。配置同时记录 use_sliding_window: false,本例不套用滑动窗口缓存缩减。Qwen2.5-7B-Instruct 配置 再明确选择 BF16 KV,每元素 2 字节,不启用 KV 量化、前缀共享或缓存卸载,TP=1、PP=1。每 token 在完整模型各层合计需要:

若一个序列已经缓存 32,768 个 token,就是 1.75 GiB。本文用“32K”指这 32,768 个已缓存总

若一个序列已经缓存 32,768 个 token,就是 1.75 GiB。本文用“32K”指这 32,768 个已缓存总 token,不是 32K 输入之外还免费附送输出空间。四条这样的序列合计 131,072 个 token,KV 为 7 GiB。 与 4.6 GiB 预算比较,第三条已经超过,四条更缺 2.4 GiB。权重能加载与这组请求不能全部保持目标 KV 状态,可以同时成立。 表中是张量载荷的理想值,不含块取整、对齐等实现成本;不能把“3.5 小于 4.6”写成两路一定能稳定服务。vLLM 的缓存规范按块描述存储,实际可用块数仍要从引擎配置和启动结果确认。KV Cache 存储规范

反过来,四条连接也不意味着始终占 7 GiB。它们若尚未增长到目标长度,实际用量会较小。本表问的是目标状态能否同时驻留,不能拿短输入试通的结果证明长尾请求组合也…

反过来,四条连接也不意味着始终占 7 GiB。它们若尚未增长到目标长度,实际用量会较小。本表问的是目标状态能否同时驻留,不能拿短输入试通的结果证明长尾请求组合也成立。当前配置的上下文上限是另一个限制;本例只算到配置中 32,768 的量级,不宣称完成上下文扩展。 两张卡的总显存可以写在资产表里,但同一个缓存分配不会自动跨进另一张卡的空闲区。容量计算必须落实到每个执行 rank——参与执行的进程及其设备——所持有的权重、层和 KV heads。 若第二张卡运行另一个完整副本,它会重新承担该副本的权重和运行开销。它能接走别的请求,却不会替第一张卡保存一条请求缺少的 KV。因此,不能把“2 × 24 GiB”直接替换进刚才单副本的算式。

若采用 TP,并且模型与实现允许按 KV heads 均匀切分,本例 4 个 KV

若采用 TP,并且模型与实现允许按 KV heads 均匀切分,本例 4 个 KV heads 在 TP=2 时每 rank 两个,在 TP=4 时每 rank 一个。只看同一组四路 32K 的 KV 载荷,每 rank 分别是 3.5 GiB 和 1.75 GiB。这里仅说明 KV 分账变化;权重、其他峰值和通信开销要按新的布局重新记录,不能假设所有项目一律除以 TP。

尤其不能无限除下去。vLLM 的 QKVParallelLinear 在 TP 数量不小于 KV head

尤其不能无限除下去。vLLM 的 QKVParallelLinear 在 TP 数量不小于 KV head 总数时,把本 rank 的 KV head 数设为 1,并计算 head 的复制份数。也就是说,适用这种路径的 GQA 模型可能复制 KV heads,而不是把一个 head 继续切成任意小数。QKV 并行层源码

News

权重装进了 24 GiB,四路 32K 上下文还装得下吗?

权重装进了 24 GiB,四路 32K 上下文还装得下吗? 模型权重已经加载,短问题也能回答,于是把服务目标改成四路长上下文。接下来遇到的却是缓存不足、请求等待,或者在某个峰值阶段显存不够。第一反应往往是:“权重才占一部分,剩下的显存为什么不够?” 加载成功只验证了当时那笔开销。生成中的历史信息也要留在 GPU…

@spots
Source: Juejin
See more like this