Prhub

#51015 [CI] Stabilize GLM-5.2 PCP evaluation

原始 PR 作者 khluu 合并时间 2026-08-05 05:14 文件变更 1 提交数 1 评论 4 代码增减 +1 / -0

执行摘要

GLM-5.2 PCP 评估启用 expandable segments 修复 OOM

PR body 表明 pytest 层报错只是 20 分钟 server-start 超时,worker 日志显示真正的失败在 profile 阶段:CUDA out of memory. Tried to allocate 24.43 GiB. 15.36 GiB is free 23.97 GiB is reserved by PyTorch but unallocated。该分配来自 FlashInfer CUTLASS MoE 的 FusedMoeRunner::getWorkspaceInfo。作者通过对照历史 run 确认这不是模型运行器回归,而是 #49294 引入 --max-num-batched-tokens 32768 后 TP1/PCP4 配置内存紧张;启用 expandable segments 是让保留内存增长/复用、避免二次连续分配的最小改动。

值得快速浏览(约 5 分钟):变更本身只有 1 行,但 PR body 的根因分析方法很有参考价值——区分表面超时与真实崩溃、用历史 Buildkite run 对照排除模型回归、把重复工作排查写进描述。设计决策上值得借鉴的是:将分配器行为收敛到确有内存压力的特定配置,而不是全局开启 expandable_segments,避免影响其他场景。建议关注后续是否有针对 FlashInfer MoE workspace 分配策略的长期优化 PR。

讨论亮点

PR 上没有出现实质性的技术争辩,也没有内联 review 评论:

  • claude[bot] 提示该 PR 来自 fork,自动 review 默认关闭,维护者可通过 @claude review 触发一次性审核;
  • 维护者 LucasWilkinson 直接批准:"LGTM; thank you!";
  • Issue 评论区只有 3 次 CI 触发命令(/runci/ci run ×2)和 GitHub Actions 的确认回复;
  • PR body 自行完成了重复工作排查,明确 #50791、#49196、#34553 与本次 OOM 无关,降低了审阅负担。

实现拆解

  1. 根因定位:通过 Buildkite #81913 的 worker 日志确认 pytest 层的失败只是表面超时,真正的崩溃发生在 profile 运行阶段,FlashInfer CUTLASS MoE 的 FusedMoeRunner::getWorkspaceInfo 尝试一次性分配约 24.43 GiB,而此时 PyTorch 已保留 23.97 GiB 却无法合并成满足请求的连续段,导致 CUDA out of memory
  2. 对照排查:同样的分配签名在 #80082(Kimi/K3 变更前)也存在,说明并非模型运行器回归或 B200 节点问题;成功运行 #80689 显示实际峰值约 159.66 GiB 非 KV 内存,低于 178.35 GiB 总量,证明以 #49294 引入 --max-num-batched-tokens 32768 为分界,TP1/PCP4 配置变得内存紧张,触发间歇性 OOM。
  3. 方案落地:在 tests/evals/gsm8k/configs/GLM-5.2-NVFP4-TP1-PCP4-EP.yamlenv 中新增 PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True,让保留的缓存段可以继续增长/复用,而不是要求第二块连续大内存;同时保留 32K batch 限制以继续覆盖大 batch PCP 路径。改动只作用于该内存紧张配置,TP2/PCP2 保持原样。
  4. 验证:Buildkite #82253(LM Eval PCP 4xB200)在 dgxB200-14 通过,profile 阶段权重 130.49 GiB、torch 峰值 28.33–30.23 GiB,服务器正常启动,1,319 个 GSM8K 示例全部通过;TP2/PCP2 控制组 GSM8K 通过;git diff --check、YAML 解析、pre-commit 均通过。
文件 模块 状态 重要度
tests/evals/gsm8k/configs/GLM-5.2-NVFP4-TP1-PCP4-EP.yaml 评估配置 modified 3.28

关键源码片段

tests/evals/gsm8k/configs/GLM-5.2-NVFP4-TP1-PCP4-EP.yaml configuration

唯一变更文件,在 env 中新增 PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True,使 FlashInfer MoE workspace 能复用已保留的缓存段,修复 TP1/PCP4 下 24.43 GiB 分配 OOM;同时保留 --max-num-batched-tokens 32768 以覆盖大 batch PCP 路径。

# GLM-5.2 TP1/PCP4 GSM8K 评估配置(tests/evals/gsm8k/configs/GLM-5.2-NVFP4-TP1-PCP4-EP.yaml)
model_name: "nvidia/GLM-5.2-NVFP4"
accuracy_threshold: 0.90
num_questions: 1319
num_fewshot: 5
max_concurrency: 100
server_args: >-
  --enforce-eager
  --max-model-len 4096
  --max-num-batched-tokens 32768  # 保留 32K 批大小,继续覆盖大 batch PCP 路径
  --safetensors-load-strategy prefetch
  --moe-backend flashinfer_cutlass
  --prefill-context-parallel-size 4
  --enable-expert-parallel
  --kv-cache-dtype fp8
env:
  # FlashInfer CUTLASS MoE 的 workspace 需要一次性分配约 24.43 GiB,
  # 普通缓存分配器因保留内存无法合并而报 OOM;
  # expandable segments 让保留段可增长复用,仅作用于该内存紧张配置。
  PYTORCH_CUDA_ALLOC_CONF: "expandable_segments:True"
  VLLM_LOGGING_LEVEL: "DEBUG"
  VLLM_USE_V2_MODEL_RUNNER: "1"

评论区精华

Fork 自动 review 默认关闭 other

claude[bot] 在 review 中说明:该 PR 来自 fork,自动 review 被禁用,维护者可评论 `@claude review` 触发一次性审核。

结论:未触发额外审核流程;人工维护者随后直接批准。 · 已解决

维护者批准 other

LucasWilkinson 评论 `LGTM; thank you!` 并批准合并,未提出代码层面的质疑。

结论:PR 获得批准,无代码层面异议。 · 已解决

风险与影响

  • 分配器行为变化expandable_segments:True 允许 PyTorch 缓存段增长/复用,可能带来常驻内存增大或碎片化;该变更只限 1 个 eval 配置,且已在 B200 上验证峰值约 30 GiB,不影响 TP2/PCP2。
  • 缓解而非根治:这是对 FlashInfer MoE workspace 大块分配请求的缓解,未改动 FusedMoeRunner::getWorkspaceInfo 本身;若 batch 大小、并行度或 PyTorch 版本变化,仍可能复发。
  • 范围与回归:不含模型输入、kernel 或数值改动,理论上无精度回归风险;但该 YAML 生效路径依赖 CI 正确读取 env 字段,若未来配置解析变化需同步验证。
  • 安全:无数据面或权限变更,无安全问题。
  • 用户:完全无感,纯 CI 评估配置变更。
  • CI 系统:GLM-5.2 TP1/PCP4 GSM8K 评估不再间歇 OOM,减少 20 分钟 server-start 超时的误报与重跑成本。
  • 团队:提供了一个低成本、配置级的 allocator 缓解范例,后续内存紧张评估可直接借鉴;同时把 FlashInfer workspace 分配问题从 CI 阻塞中剥离出来,便于后续单独优化。
显存分配行为 测试配置变更 缓解而非根治

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论