Kestrel_VLLM - 21 · 收益区间实测界定:KV 分页与 L3 驻留为何被判「不做」

21 · 收益区间实测界定:KV 分页与 L3 驻留为何被判「不做」

一句话 :按原计划,KV 复用迁移到 GPU 后还剩两站(P2 KV 分页、GPU 侧 L3 分层驻留),两者都预设「GPU 显存是瓶颈」;本篇先把这个前提量化,结论是不做 ------并写清什么条件下结论会翻转。 前置 :建议先读 第 19 篇 与 第 20 篇(KV 复用迁移的上下篇)。 环境 :x86-64 + NVIDIA RTX 5090(32.6 GB)· Qwen3-30B-A3B q4local · max_seq=8192。

状态:⛔ 实测门禁未通过 → P2 与 GPU 侧 L3 驻留均不作(已入档)。

一、问题与结论

  1. 门禁先于实现:P2 的价值全部来自「回收镜像里没被写入的部分」。所以先量这个上界,量出来不划算就不写代码 ------ 而不是先实现块表再说。
  2. 镜像单槽 = 415,236,096 B ≈ 396 MiB (nl·max_seq·(2·kv_dim + 8·nkv),本机 30B-A3B)。
  3. 最重档峰值只用到 60.2% :memory.total = 32607 MiB,峰值 used = 19625 MiB → 余量 12982 MiB。
  4. 判定 :分页可回收的上界 (= 镜像未写入部分)≤ 396 MiB/槽,占总量 1.2% ;而余量有 12.98 GiB。显存不是瓶颈 ⇒ P2 不作 。GPU 侧 L3 驻留依赖同一瓶颈假设 ⇒ 同样不作。
  5. 边界必须一起写 :结论绑定「32.6 GB 卡 + ~18 GiB 权重常驻 + max_seq=8192」。换小显存卡 / 更大模型 / 把 max_seq 抬到 40960,需重测后再议。
  6. 按「精度口径」这条纪律,这是 x86/RTX 5090 口径,不可读作 RK3588 结论。

二、背景:为什么这两站需要先过门禁

迁移方案里 P2 的目标写得很直白:「长上下文显存收益」 。也就是说,它并不改吞吐、不改数值(分页只是把「连续偏移寻址」换成「块表两步寻址」),唯一的收益是显存峰值下降。

于是这段投入是否值得,完全取决于一个可测量的事实:显存是不是瓶颈。如果余量本来就有十几 GiB,那么:

  • 收益上界 = 镜像未写入的部分(上下文越满越少,满窗时为 0);
  • 成本 = 改三个 attention 内核的行寻址 + 与 VLLM_CUDA_GRAPH 图捕获的组合验证(图里固化的是镜像基址,改寻址后必须重验开/关两种状态)。

这正是「收益区间实测界定」这条方法论原则要挡的情况:先拿到收益上界,再决定是否付实现成本。

三、核心机制:显存口径怎么定

要判断「够不够」,先得知道本机显存是怎么被留出来的。设备侧权重缓存(wcache)的默认预算取自「空闲显存的一半,上限 24 GiB」(src/npu/cuda/vllm_cuda_kernels.cu):

c 复制代码
/* 文件名:src/npu/cuda/vllm_cuda_kernels.cu,vcuda_dev_create() */
if (s->budget == 0) {
    size_t freeb = 0, totb = 0;
    if (cudaMemGetInfo(&freeb, &totb) != cudaSuccess) {
        freeb = prop.totalGlobalMem / 2;
    }
    /* Default: half of the free device memory, capped at 24 GiB. ... */
    s->budget = freeb / 2;
    const size_t cap = (size_t)24 << 30;
    if (s->budget > cap) s->budget = cap;
    if (s->budget < (size_t)256 << 20) s->budget = (size_t)256 << 20;
}

也可以用环境变量强制覆盖(src/npu/cuda/vllm_cuda.c):

c 复制代码
/* 文件名:src/npu/cuda/vllm_cuda.c */
size_t budget_mb = cfg ? cfg->wcache_mb : 0;
{
    const char *e = getenv("VLLM_CUDA_WCACHE_MB");
    if (e && e[0]) { long v = atol(e); if (v > 0) budget_mb = (size_t)v; }
}

峰值大头是权重与预加载,而不是 KV;wcache 条目数的期望值也与 MoE 结构有关(src/main.c):

c 复制代码
/* 文件名:src/main.c */
/* wcache 条目期望值:稠密每层 7 single + 2 fused。MoE 层的 gate/up/down
 * 与 fused GU 走独立专家缓冲(d_moe_*),不占 wcache 条目,故每层只有
 * q/k/v/o + fused QKV = 5 条。两者都再加 1 个 lm_head。 */
const int want_wc  = cfg->n_layers * (cfg->is_moe ? 5 : 9) + 1;

3.1 镜像几何

text 复制代码
模型: Qwen3-30B-A3B-q4local (config.json)
  num_hidden_layers = 48        num_key_value_heads = 4
  head_dim = 128                → kv_dim = 4 × 128 = 512
运行时: [STREAM] vqf_load OK: dim=2048 layers=48 heads=32 kv=4 ffn=98304 vocab=151936 max_seq=8192

镜像单槽 = nl × max_seq × (2 × kv_dim + 8 × nkv)      # 2 个 int8 K/V(1B)+ 2 个 f32 scale(4B)
        = 48 × 8192 × (2×512 + 8×4)
        = 48 × 8192 × 1056
        = 415,236,096 B ≈ 396 MiB          (占 memory.total 的 1.2%)

按 VC_KV_SLOTS = 8 全部占满算:≈ 3.09 GiB(9.5%)。但只有真正做 append 的 state 才分配,所以实际开销正比于并发 state 数。

四、实测数据

4.1 峰值显存

用 500 ms 采样的 nvidia-smi 盯最重档(权重驻留 + 全 GPU decode + 位级档,实测):

text 复制代码
$env:VLLM_CUDA_DECODE=1; $env:VLLM_CUDA_INFER=1; $env:VLLM_CUDA_FORCE_CPU=1; $env:VLLM_CUDA_L2EXACT=1
.\vllm_kestrel_x64.exe --cuda --model <30B-A3B-q4local> --stream-test --stream-n 4

memory.total = 32607 MiB
idle  used   =   936 MiB
peak  used   = 19625 MiB  (60.2%)        ← 500 ms 采样
→ 峰值余量   = 12982 MiB

(VLLM_CUDA_INFER=1 的权重缓存预算是「空闲显存的一半」≈ 15495 MiB,实测 289/433 个权重驻留、设备缓存 1845.8 MB ------ 即峰值的大头是权重与预加载,不是 KV。)

4.2 结论表

量 值 占总显存
镜像单槽 396 MiB 1.2%
8 槽全分配 3.09 GiB 9.5%
分页可回收上界(镜像未写入部分) ≤ 396 MiB/槽(满窗时为 0) ≤ 1.2%
峰值余量 12982 MiB 39.8%

收益上界 ≤ 1.2%,余量 39.8% ⇒ 不是瓶颈。

五、边界:什么时候这个结论会翻转

写「不做」时必须同时写下边界,否则这条判定会在别的机器上被误用:

变量 本机口径 翻转子
显存 RTX 5090 32.6 GB 更小的卡(如 24 GB 及以下)
权重常驻 ~18 GiB(30B-A3B q4) 更大模型 / 更高精度权重
max_seq 8192 抬到 40960 → 镜像单槽 ≈ 1.98 GiB
并发 state 1--4 serve 大 batch 同时开 CUDA → 槽位数 × 396 MiB

也就是说:当「镜像总占用」相对「余量」不再是小量时(经验上 >10%),这道门就该重测。 另外,GPU 侧 L3 驻留的价值是「省显存换更长上下文 / 更高并发」,与 P2 依赖同一个前提,所以本判定一并覆盖它。

口径纪律:任何 GPU 数字不得当作 RK3588 的声明。本篇全部为 x86 + RTX 5090 实测,不能外推到 ARM 板端。

CPU 对照(迁移前基线)

  • CPU 参考:CPU 侧无对应实现(GPU 显存口径)------ 迁移前的 CPU 引擎不存在 device 显存预算这一对象。
  • 迁移要点 :无迁移(判「不作」):镜像单槽 ≈396MiB(占总量 1.2%)、峰值余量 12.98GiB ⇒ 显存非瓶颈;写清翻转边界(更小卡 / 更大模型 / max_seq 抬到 40960)。
  • 真机验证 :未独立复现:需 30B-A3B + 500ms 采样 nvidia-smi 峰值显存(max_seq=8192)。

六、小结

  1. 预注册门禁要可量化。如果门禁只写「显存是否瓶颈」,那永远可以论证两边;写成「量化镜像占用 vs 峰值余量」之后,结论是一张表就能定的。
  2. 收益上界比收益估计更省事。不需要实现块表来测「能省多少」------ 结构上界就是「镜像里没被写入的部分」,一行乘除即可。
  3. 「不做」也要入档,并写边界 。判否项同样是结论;不写边界,下一个机器上就会有人拿它当依据。(本系列 第 12 篇、第 13 篇 的三值量化、Tiling、Tensor Core 判否也是同一处理方式。)
  4. 同一个技术换硬件就可能翻转 。CPU 的 L3 收益来自 RAM 紧张(v2 方案实测 KV 底座 2.35 GB / RSS 2.66 GB,收益是「单层档」量级的降幅),GPU 上显存宽松 → 不成立。不照搬跨硬件结论是「收益必须实测界定」这条原则的核心要求。

相关篇目:第 12 篇、第 13 篇、第 19 篇、第 20 篇 源码与配套资源:本仓库 gitee.com/pei-xiaogua...; CPU 推理源码 gitee.com/pei-xiaogua...

相关推荐
自养Agent1 小时前
AI 私有化实战:一张卡能扛几个并发,答案不在显卡参数里
人工智能
长弓三石1 小时前
企业级开源Harness平台BizBuddy 0.9.9 发布:知识库混合检索与长期记忆托管
人工智能
一线数智1 小时前
来腾讯云AI开放日 加入人类职业进化计划
大数据·人工智能·腾讯云
桦说编程1 小时前
别再追“最强模型”了,先想清楚你要什么
人工智能·llm·agent
loulanyue_1 小时前
机器换人不是终点,混合智能体重塑制造范式:从自主四要素到组织扁平化破局——读周济李培根院士2026东湖论坛国际智能制造创新论坛演讲实录
大数据·人工智能·制造
龙亘川2 小时前
适应人工智能发展、构建就业友好型发展方式
大数据·运维·人工智能·信息可视化·智慧城市
实验室管理云平台2 小时前
某国家重点实验室应用经费合同管理系统,实现经费实时监控
大数据·人工智能
武子康2 小时前
HunyuanVideo-1.5 首帧视频怎么做提示词对照?先查清 rewrite 是否生效
人工智能·后端·agent