Prhub

#43082 [CI] Fix "test_vit_cudagraph_[image|video][step3_vl]" failure

原始 PR 作者 haosdent 合并时间 2026-05-21 12:22 文件变更 1 提交数 2 评论 12 代码增减 +26 / -4

执行摘要

修复 Step3-VL 编码器 CUDA Graph 测试 OOM

PR #42224 引入的 Step3-VL 编码器 CUDA Graph 测试在 daily CI 的 L4 (22 GiB) 上因模型权重 19+ GiB 及默认编码器 cudagraph budget range 导致 OOM。PR body 直接引用 Buildkite 构建 #66759 的失败日志,目标是修复 CI 稳定性,同时保留测试覆盖。

值得合并,该 PR 精准修复了 CI OOM 问题,且保留了关键测试覆盖。重构的 compilation_config_overrides 模式可作为其他编码器 CUDA graph 测试的参考。CI 配置改用标签机制是良好实践。

讨论亮点
  1. CI 扩展性和标签系统:

    • @DarkLight1337 质疑为何不将 step3_vl 测试放在 Extended 1(更广泛的测试 machine)中运行。@haosdent 解释 Extended 1 使用 L4 (22 GiB) GPU,直接跑会 OOM。
    • @DarkLight1337 建议改用标签(tag)而非手动匹配文件名来组织测试,提高可扩展性。@haosdent 接受建议,最终方案:在 Extended 1 中添加 --ignore 排除该文件,同时在另一条命令中使用 -m 'not core_model' 来运行。
  2. 虚拟模型方案 vs. 跳过测试:

    • @Isotr0py 指出完全跳过 L4 测试存在风险,因为 step3_vl 的编码器 CUDA graph 实现将失去测试覆盖。他建议使用 hf_overrides 将模型缩小为 dummy 模型,并降低 budget size,这与最终采用的方案一致。@haosdent 随后实现了该方案。

实现拆解

  1. 修改 Step3-VL 测试配置 (tests/models/multimodal/generation/test_vit_cudagraph.py):

    • VitCudagraphTestConfig 类中新增 compilation_config_overrides 字段,允许单个测试覆写编译配置。
    • step3_vl 配置项中的 modalities 明确设为 ["image"],不再支持 video 模态,使得 test_vit_cudagraph_video 执行 pytest.skip,避免实际运行。
    • 添加 compilation_config_overrides 字典,设置 encoder_cudagraph_token_budgets=[1152],单一 bucket 恰好覆盖最大测试图片的输出 token 数(1141),避免默认自动推测生成多个 power-of-2 bucket 导致内存膨胀。
    • 通过 vllm_runner_kwargs 使用 load_format="dummy"partial(dummy_hf_overrides, model_arch="StepVLForConditionalGeneration") 加载随机权重(仅保留 1 个文本层和 1 个视觉层),跳过 20 GiB 权重下载,内存占用从 19.17 GiB 降至 6.59 GiB。
  2. 重构 get_compilation_config 函数:

    • 修改函数签名,接受 config: VitCudagraphTestConfig 参数,返回基础编译配置合并 config.compilation_config_overrides,实现了配置的灵活覆写。
    • 更新 test_vit_cudagraph_imagetest_vit_cudagraph_video 中的调用,传入 config 对象。
  3. CI 配置变更(.buildkite/test_areas/models_multimodal.yaml):

    • 移除在 Extended 1 中单独添加 -k step3_vl 的命令,改为在 Extended 1 中增加 --ignore models/multimodal/generation/test_vit_cudagraph.py 参数,避免在内存较小的 L4 上运行该测试。
    • 新增一个独立的测试命令(在内存更大的测试环境中),通过标签 not core_model 排除 core model 测试,使用 models/multimodal/generation/test_vit_cudagraph.py -m 'not core_model' 仅运行 step3_vl 等非核心模型测试。
文件 模块 状态 重要度
tests/models/multimodal/generation/test_vit_cudagraph.py 测试 modified 6.04
.buildkite/test_areas/models_multimodal.yaml CI modified 3.0

关键符号

get_compilation_config test_vit_cudagraph_image test_vit_cudagraph_video

关键源码片段

tests/models/multimodal/generation/test_vit_cudagraph.py test-coverage

核心变更文件:通过 dummy 权重、单一 budget bucket、模态限制解决了 OOM 问题;新增 compilation_config_overrides 字段和重构 get_compilation_config 函数提供了可扩展的配置覆写模式。

# tests/models/multimodal/generation/test_vit_cudagraph.py
# 关键配置变更from functools import partial # 新增导入
from ....utils import dummy_hf_overrides # 新增导入@dataclass
class VitCudagraphTestConfig:
    # ... 原有字段 ...
    compilation_config_overrides: dict = field(default_factory=dict) # 新增:允许单个测试覆写编译配置# Step3-VL 配置重写
MODEL_CONFIGS = {
    # ... 其他模型 ...
    "step3_vl": VitCudagraphTestConfig(
        model="stepfun-ai/Step3-VL-10B",
        modalities=["image"], # 限制仅 image 模态,video 测试将跳过
        image_prompt=step3_vl_chat_template("What is in this image?"),
        # 使用单 bucket [1152] 覆盖最大图片输出 token 数,避免多 power-of-2 bucket 导致内存膨胀
        compilation_config_overrides={
            "encoder_cudagraph_token_budgets": [1152],
        },
        # 使用 dummy 权重(仅 1 text + 1 vision layer)和随机权重,避免下载 20 GiB
        vllm_runner_kwargs={
            "load_format": "dummy",
            "hf_overrides": partial(
                dummy_hf_overrides,
                model_arch="StepVLForConditionalGeneration",
            ),
        },
    ),
}# 重构 get_compilation_config 支持覆写
def get_compilation_config(config: VitCudagraphTestConfig):
    return {
        "cudagraph_mm_encoder": True,
        "encoder_cudagraph_max_vision_items_per_batch": 1,
        "encoder_cudagraph_max_frames_per_batch": 16,
        **config.compilation_config_overrides, # 合并覆写配置
    }

评论区精华

CI 配置组织方式:手动路径 vs 标签 设计

@DarkLight1337 质疑将测试单独加入 CI 命令的方式不可扩展,建议使用标签选择。@haosdent 最初解释因 GPU 不同导致 OOM,后接受建议改用标签。最终方案:在 Extended 1 中添加 --ignore,并在独立命令中使用 -m 'not core_model'。

结论:改用标签机制:Extended 1 添加 --ignore 排除该文件,独立命令通过标签运行,提高可维护性。 · 已解决

是否应直接跳过 L4 上的测试 测试

@Isotr0py 认为直接跳过测试有风险,建议使用 dummy 模型 + 降低 budget size 以保留覆盖。@haosdent 最终采纳该方案,实现内存优化,使测试可在 L4 上运行。

结论:不跳过,而是使用 dummy 权重和单一 budget bucket 使测试能在 L4 上运行。 · 已解决

风险与影响

  1. 测试覆盖退化风险: 使用 dummy 权重(仅 1 层)代替完整 10B 模型,可能无法暴露与完整模型特定层数或权重分布相关的编码器 CUDA graph 问题。但测试本身仅验证 capture/replay 功能性,非精度验证,风险可控。
  2. CI 配置维护负担: 新的 CI 配置在 Extended 1 中添加了 --ignore 并在另一命令中运行该测试,增加了配置复杂度;但已通过标签机制和注释提高可维护性。
  3. 单 bucket budget 的有效性: 硬编码 token budget 为 [1152] 依赖当前最大图片 cherry_blossom 输出 token 数(1141),若未来图片解析或模型输出变化,可能需要调整。但测试灵活性已通过 compilation_config_overrides 保留。
  1. CI 稳定性修复:消除了 daily CI 中 step3_vl 测试在 L4 GPU 上的 OOM 失败。
  2. 测试覆盖保持:通过 dummy 模型和内存优化,保留了 step3_vl 的编码器 CUDA graph 功能测试,未完全跳过。
  3. 代码库可维护性:新增 compilation_config_overrides 字段和重构 get_compilation_config 函数,为未来其他模型测试覆写编译配置提供了通用模式。
  4. CI 配置组织:通过标签而非手动路径选择测试,提高了扩展性和可读性。
测试覆盖可能退化(dummy 模型) CI 配置复杂度增加

关联 Issue

#42224 [MM][CG] Enable encoder Cudagraph for Step3VL

完整报告

参与讨论