Prhub

#2700 feat(ci): add stage-c-8-gpu-b200 for the Blackwell runner

原始 PR 作者 yueming-yuan 合并时间 2026-08-30 14:37 文件变更 8 提交数 1 评论 0 代码增减 +53 / -11

执行摘要

新增 stage-c-8-gpu-b200,接入 8×B200 CI runner

PR body 明确这是 Blackwell CI 的 Chain 1/5,目标是把 8×B200 主机纳入现有 CI stage 体系,为后续 b200-ci-hardware-axis、b200-ci-baseline-identity、b200-ci-dispatch、b200-ci-enable-tests 逐步在 Blackwell 硬件上跑测试铺路。作者强调两个约束:一是主机刻意不分区——「an 8-GPU runner cannot share a node with 2/4-GPU runners without both claiming the same devices, and GitHub has no cross-runner resource lock」;二是合入前置条件——runner 必须已在线,否则「the nightly cron would queue a ["b200","8gpu"] job that no runner can claim」。prerequisite 已确认完成:b200-oma-8gpu-0 online,radixark/miles:dev 在 sm100 上验证通过(torch 2.11.0+cu130,capability (10,0),8 devices,bf16 matmul)。

值得快速精读。虽然单看只是注册表加一行 + 一个 workflow job,但其中蕴含两个可复用的 CI 设计原则:一是「测试自声明 GPU 预算(ray start --num-gpus / torchrun --nproc-per-node)而不是读取可见设备」,这让不分区主机的资源分配语义清晰;二是「合入时零测试注册是安全的,因为空 stage 收集零测试并退出 0」,支撑了增量迁移的分步落地。对参与 CI 基础设施维护的工程师,建议重点关注 pr-test.yml 中 job 注释与 tests/ci/run_suite.py 的 suite 注释,这两处把「为什么这么设计」讲得最清楚。

讨论亮点

本 PR 没有产生实质 review 讨论:review_comments_count 为 0,唯一的 review 交互是 claude[bot] 的自动提醒(提示仓库配置了手动 review,可 @claude review)和 guapisolo 的空 body APPROVED。设计上的两个关键权衡——「不分区」和「零测试注册也合入」——都在 PR body 与代码注释中预先论证,未经过 review 交锋:不分区是因为 GitHub 没有跨 runner 资源锁,任何 2/4-GPU runner 与 8-GPU runner 共存都会争抢同一批物理设备;零测试注册是因为 stage 在没有启用注册时收集零测试并退出 0,属于增量迁移期的预期状态,验证责任在链路第 5 个 PR(b200-ci-enable-tests)。

实现拆解

  1. Suite 注册:在 tests/ci/run_suite.pyCI_SUITES[HWBackend.CUDA] 列表末尾追加 stage-c-8-gpu-b200,并重写模块顶部注释,说明三个 8-GPU 整节点 suite(H100/H200/B200)与 H200 拆分车队(2+2+4,按 CUDA_VISIBLE_DEVICES 分区)的差异,以及 Blackwell 主机不分区、子 8-GPU 测试也注册到本 suite 的原因。
  2. Stage 选择与 runner 映射:在 tests/ci/stage_selection.pyPR_GPU_STAGES 中加入 stage-c-8-gpu-b200,使 PR 变更路径扇出时能选中该 stage;在 tests/ci/file_run.pyCUDA_SUITE_RUNS_ON 中加入 "stage-c-8-gpu-b200": ["b200", "8gpu"] 映射,保证 /rerun-test 文件运行链路(run-ci-file.yml 的 resolve-file-run job)能解析到新 runner。
  3. Job 接线:在 .github/workflows/pr-test.yml 末尾追加 stage-c-8-gpu-b200 job,与其它 GPU stage 保持同一 gate 模式(needs: [resolve-ci-policy, resolve-ci-image, stage-a-cpu],包含 skipped_stages fail-open 判断和 bypass_fastfail 门),复用 _run-ci.yml 可复用工作流,以 --suite stage-c-8-gpu-b200 调用 run_suite.py
  4. 锁测试同步:更新 tests/ci/test/test_run_suite.py 中所有 stage 数量断言——test_cuda_suites_exact 追加新 suite 名、command 块计数 7→8、_run-ci.yml 引用 5→6、manual_scope 计数 5→6、bypass/fail-open gate 计数 5→6。这些锁测试确保新 stage 必须遵守现有策略 seam 和 gate 约定,防止配置漂移。
  5. 文档配套tests/ci/README.md 记录 b200-oma-8gpu-0 主机约定(整节点、CVD 未设置、刻意不分区);docs/ci/00-stage.md 将 stage 命名规则的 hw 集合扩展为 {cpu, h100, h200, b200, mi350},并在 roster 表新增一行;docs/ci/contributor-guide.md 补充 Blackwell suite 选择指引(nvfp4、mxfp8 等需要 Blackwell 硬件的测试)。
文件 模块 状态 重要度
.github/workflows/pr-test.yml CI 工作流 modified 4.68
tests/ci/run_suite.py 套件注册 modified 4.13
tests/ci/test/test_run_suite.py 套件测试 modified 3.79
tests/ci/file_run.py 文件运行 modified 3.28
tests/ci/stage_selection.py 阶段选择 modified 3.11
tests/ci/README.md 测试文档 modified 2.02
docs/ci/00-stage.md CI 文档 modified 1.96
docs/ci/contributor-guide.md CI 文档 modified 1.18

关键符号

CI_SUITES PR_GPU_STAGES CUDA_SUITE_RUNS_ON test_cuda_suites_exact test_every_stage_consumes_resolved_policy test_cpu_and_gpu_stages_use_dedicated_reusable_workflows test_dispatch_has_no_scope_input_but_runs_all_cuda_domains test_gpu_gates_consume_shared_bypass_output

关键源码片段

.github/workflows/pr-test.yml infrastructure

新增 stage-c-8-gpu-b200 job 是本次核心接线:runs_on ["b200","8gpu"]、复用 _run-ci.yml、与其它 GPU stage 完全一致的四重 gate(policy/image/cpu-gate/bypass),并附带整段设计注释说明为什么不分区。

# Blackwell fleet 是单台未分区的 8-GPU 主机:8-GPU runner 无法与
# 2/4-GPU runner 共存于同一节点,否则 GitHub 会把 job 派发到
# 重叠的设备上(GitHub 没有跨 runner 的资源锁)。
# 少于 8 卡的 Blackwell 测试也注册到本 suite;不设分区矩阵,
# 单个 runner 串行处理 shard,当前预算远在 job 超时之内。
stage-c-8-gpu-b200:
  needs: [resolve-ci-policy, resolve-ci-image, stage-a-cpu]
  if: |
    always() && !cancelled() &&
    needs.resolve-ci-policy.result == 'success' &&
    needs.resolve-ci-image.result == 'success' &&
    !contains(fromJSON(needs.resolve-ci-policy.outputs.skipped_stages || '[]'), 'stage-c-8-gpu-b200') &&
    (needs.stage-a-cpu.result == 'success' ||
     needs.resolve-ci-policy.outputs.bypass_fastfail == 'true')
  uses: ./.github/workflows/_run-ci.yml
  with:
    runs_on: '["b200", "8gpu"]'
    container_image: ${{ needs.resolve-ci-image.outputs.container_image }}
    ref: ${{ inputs.ref || '' }}
    execute_command: >-
      python tests/ci/run_suite.py --hw cuda --suite stage-c-8-gpu-b200
      --cadence ${{ needs.resolve-ci-policy.outputs.cadence }}
      --labels ${{ needs.resolve-ci-policy.outputs.raw_labels }}
      ${{ github.event_name == 'workflow_dispatch' && '--match-all-labels' || '' }}
  secrets: inherit
tests/ci/run_suite.py configuration

CI_SUITES 是 suite 注册的事实来源,新增 stage-c-8-gpu-b200 后,所有 policy 解析、测试筛选、skip 报告都会自动感知新 suite;同步改写的注释阐明了不分区设计。

# CUDA suites:每个 suite 由 .github/workflows/pr-test.yml 中对应的
# workflow job 提供。stage-c-8-gpu-h100 / stage-c-8-gpu-h200 /
# stage-c-8-gpu-b200 运行在整节点 8-GPU 主机上;H200 拆分车队是一台
# 8-GPU 节点通过每个 runner 的 CUDA_VISIBLE_DEVICES 分为 2+2+4 个
# worker(参见 pr-test.yml 中 stage-c-4-gpu-h200 / stage-b-2-gpu-h200 /
# stage-c-2-gpu-h200 job 注释)。Blackwell 单台主机不分区,因此
# 2/4-GPU 的 Blackwell 测试也注册到 8-GPU suite —— 测试通过
# ray start --num-gpus 或 torchrun --nproc-per-node 声明自己的预算,
# 而不是读取可见设备。
CI_SUITES = {
    HWBackend.CPU: [
        "stage-a-cpu",
        "stage-b-cpu",
    ],
    HWBackend.CUDA: [
        "stage-b-2-gpu-h200",
        "stage-c-8-gpu-h100",
        "stage-c-8-gpu-h200",
        "stage-c-4-gpu-h200",
        "stage-c-2-gpu-h200",
        "stage-c-8-gpu-b200", # 新增:Blackwell 8-GPU 整节点 suite
    ],
    HWBackend.ROCM: [
        # 由 pr-test-rocm.yml 消费。
        "stage-c-4-gpu-mi350",
        # 由外部 sgl-project/sglang MI350 nightly 消费。
        "nightly-stage-c-8-gpu-mi350",
        "nightly-stage-c-4-gpu-mi350",
        "nightly-stage-c-2-gpu-mi350",
    ],
}

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

  1. 外部 runner 依赖:PR body 明确指出合入前提是 b200-oma-8gpu-0 已在线(已确认)。但若该 runner 后续下线或标签缺失,schedule 触发的 nightly cron 对 skipped_stages 为空,会持续排队一个无人认领的 ["b200","8gpu"] job,造成 CI 挂起。
  2. 零测试覆盖空洞:当前没有任何启用的测试注册到 stage-c-8-gpu-b200,stage 收集零测试并以 0 退出,属于有意设计。真正的执行验证(sm100 上的 torch/cuda 兼容、BF16 matmul、容器内 ray/torchrun 启动)要等链路第 5 个 PR(b200-ci-enable-tests)才发生,在此之前 b200 路径从未被真实 job 跑过。
  3. 资源利用率:不分区意味着 2/4-GPU 的 Blackwell 测试会空闲 4-6 张 GPU;单分片 job 串行化 shard,若后续 Blackwell 测试量增长超出 job 超时预算,会需要重新引入分区矩阵或并发 runner。
  4. 镜像与硬件兼容性:验证了 radixark/miles:dev 在 sm100 上可运行(capability (10,0)),但后续若镜像构建目标不含 Blackwell 相关的 CUDA 能力(nvfp4/mxfp8 kernel),启用测试后会暴露新的失败模式。

对系统:CI stage 分类体系新增第四种 NVIDIA 硬件类 b200,PR 与 schedule 两条触发路径都会把新 stage 纳入策略解析和 gate 计算;/rerun-test 文件运行链路同步具备解析能力。对团队:Blackwell 相关测试(nvfp4、mxfp8 等)从此有了明确的归属 suite,贡献者指南给出选择指引,降低后续接入成本。对用户:无任何面向终端用户的行为变化。影响程度为低到中——纯 CI 基础设施配置变更,但它是 5-PR 链的入口,后续 4 个 PR 将逐步把 Blackwell 测试纳入常规 CI,最终影响面会扩大。

依赖外部 runner 在线 新 stage 零测试覆盖 GitHub 无跨 runner 资源锁 Blackwell 新硬件平台

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论