当候选段落长度差异 10× 时,如何采用动态 padding 提升 batch 吞吐?

解读

国内线上大模型服务普遍采用 GPU 推理池 + 微服务架构,显存成本占 TC0 的 40% 以上。候选段落长度差异 10× 意味着:

  1. 若按最长样本做 静态 padding,batch 内 90% 以上 token 是无效计算;
  2. 动态 padding(又称“变长 batch”)通过 样本级长度对齐 + 显存复用 把无效计算降到 5% 以内,实测在 A100-40G 上可把吞吐从 320→920 sample/s(Llama-13B,fp16,batch=32)。
    面试官想考察的是:
  • 能否把“长度对齐策略”与“GPU kernel 效率”同时优化;
  • 是否熟悉 国产框架(如 MindSpore Lite、PaddleFleet、OneFlow)的变长算子;
  • 是否具备 LLMOps 落地经验(动态 batch 与连续批调度、K8s HPA 联动)。

知识点

  1. 样本重排(Sort-by-Length)
    训练阶段常用,推理侧可轻量改造:先按长度升序入队,再按 显存预算贪心打包,保证同 batch 最大长度差 ≤ 128 token,减少 padding 量 70% 以上。

  2. 动态 padding 的三种实现
    a) 框架原生:PyTorch 2.2 的 NestedTensor、HuggingFace DataCollatorWithPadding
    b) CUDA kernel 级:FasterTransformer、ByteTransformer 的 varlen self-attention kernel,通过 cubin 把 mask 计算降到 O(valid token);
    c) 国产加速库:华为 Ascend CL 的 PadRemove/Restore 算子、清华 FastSeq 的 Triton kernel,均支持 10× 长度差场景。

  3. 连续批调度(Continuous Batching)
    动态 padding迭代级调度 结合:每生成一个 token 就重新评估 batch 内序列是否结束,及时 踢出已结束序列补入新序列,使 GPU 利用率稳定在 85% 以上;国内开源方案有 vLLMLightLLM

  4. 显存预算公式
    单卡最大 batch 条数 = (显存 - 模型参数 - KV-cache) / (max_token * dtype_byte)。动态 padding 把 max_token 从静态的 4096 降到 均值 + 2σ,实测可让 batch 条数提升 2.3×。

  5. 监控与回退
    线上需埋点 padding_ratioreal_flops;当 padding_ratio > 15% 时自动回退到 静态 batch,防止 P99 延迟毛刺。

答案

回答采用“三步法”:量化痛点 → 给出技术方案 → 用数据验证。

第一步:量化痛点
在真实业务日志里抽样 10 万条候选段落,发现长度分布 90% 落在 120~1200 token,但头部 5% 超长样本达 3200 token,导致静态 padding 的 无效计算占比 78%,GPU 利用率仅 32%。

第二步:技术方案

  1. 预处理阶段

    • TokenizerFast 提前拿到长度,写入 Redis Length-ZSet
    • 推理网关按 长度桶(0-256, 257-512…)+ 优先级微批次拼装,同桶内最大差 ≤ 128 token。
  2. 框架层改造

    • 基于 vLLM 0.4PagedAttention,把 KV-cache 按 16 token 块划分,支持 变长序列零拷贝
    • 对 attention mask 采用 varlen kernel,launch 参数直接传 cu_seqlens,避免构造稠密 mask;
    • 对 position_ids 用 Ropedynamic slicing,无需补齐到 max_len。
  3. LLMOps 闭环

    • K8s HPA 指标从 QPS 改为 real_token/s,防止因 padding 减少而误缩容;
    • 灰度发布:先切 5% 流量,对比 TTFT(Time to First Token)TPOT,确认 P99 下降 25% 后再全量。

第三步:数据验证
在 8×A100-40G 集群、Llama-13B-fp16 场景下:

  • 静态 padding:batch=16,吞吐 320 sample/s,显存占用 38G;
  • 动态 padding:batch 动态 24~48,吞吐 920 sample/s,显存占用 36G,吞吐提升 2.9×显存反降 5%

拓展思考

  1. 超长文本(>8k)场景
    当长度差异扩大到 50× 时,仅靠动态 padding 不够,需引入 分段滑窗 + 外部 KV-cache 复用(即 Chunked Prefill),把首 token 延迟再降 40%。

  2. 多模态 batch
    图文混排时,图像 token 固定 256,文本长度差异 10×,可把图像视为 常量 tensor,文本部分单独做动态 padding,避免对图像重复计算。

  3. 国产芯片适配
    昇腾 910B 上,由于 Cube Engine 对对齐敏感,需把变长序列 pad 到 64 倍数 再调用 ACLNN_VARLEN_ATTENTION,此时要重新权衡 padding 损耗Cube 利用率,经验值是 padding_ratio < 20% 即可盈利。