执行摘要
- 一句话:新增 stage-c-8-gpu-b200,接入 8×B200 CI runner
- 推荐动作:值得快速精读。虽然单看只是注册表加一行 + 一个 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 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)。
实现拆解
- Suite 注册:在
tests/ci/run_suite.py 的 CI_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 的原因。
- Stage 选择与 runner 映射:在
tests/ci/stage_selection.py 的 PR_GPU_STAGES 中加入 stage-c-8-gpu-b200,使 PR 变更路径扇出时能选中该 stage;在 tests/ci/file_run.py 的 CUDA_SUITE_RUNS_ON 中加入 "stage-c-8-gpu-b200": ["b200", "8gpu"] 映射,保证 /rerun-test 文件运行链路(run-ci-file.yml 的 resolve-file-run job)能解析到新 runner。
- 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。
- 锁测试同步:更新
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 约定,防止配置漂移。
- 文档配套:
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 工作流;类别 infra;类型 infrastructure): 新增 stage-c-8-gpu-b200 job 是本次核心接线:runs_on ["b200","8gpu"]、复用 _run-ci.yml、与其它 GPU stage 完全一致的四重 gate(policy/image/cpu-gate/bypass),并附带整段设计注释说明为什么不分区。
tests/ci/run_suite.py(模块 套件注册;类别 test;类型 configuration;符号 CI_SUITES): CI_SUITES 是 suite 注册的事实来源,新增 stage-c-8-gpu-b200 后,所有 policy 解析、测试筛选、skip 报告都会自动感知新 suite;同步改写的注释阐明了不分区设计。
tests/ci/test/test_run_suite.py(模块 套件测试;类别 test;类型 test-coverage;符号 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): 锁测试是本 PR 的验收网:所有 stage 数量断言(7→8、5→6 等)确保新 stage 必须遵守既有策略 seam、gate 约定和 fail-open skip 列表,防止配置漂移静默通过。
tests/ci/file_run.py(模块 文件运行;类别 test;类型 configuration;符号 CUDA_SUITE_RUNS_ON): CUDA_SUITE_RUNS_ON 是 /rerun-test 文件运行链路解析 runner 标签的映射表,缺了它,显式请求单个 Blackwell 测试文件时就无法路由到 b200 runner。
tests/ci/stage_selection.py(模块 阶段选择;类别 test;类型 configuration;符号 PR_GPU_STAGES): PR_GPU_STAGES 决定 PR 变更路径扇出到哪些 GPU stage,新增条目后,任何改动 Blackwell 测试或相关源码的 PR 都会自动把 stage-c-8-gpu-b200 纳入可选中集合。
tests/ci/README.md(模块 测试文档;类别 docs;类型 documentation): 记录 b200-oma-8gpu-0 主机约定(整节点、CVD 未设置、刻意不分区),是后续维护者理解 Blackwell fleet 资源语义的第一手文档。
docs/ci/00-stage.md(模块 CI 文档;类别 docs;类型 documentation): stage 命名规则与 roster 表是 CI stage 体系的规范文档,hw 集合加入 b200 并新增一行,保证新硬件类有据可查。
docs/ci/contributor-guide.md(模块 CI 文档;类别 docs;类型 documentation): 贡献者选择 suite 的对照表新增 Blackwell 指引,帮助测试作者为 nvfp4、mxfp8 等硬件相关测试选对归宿。
关键符号: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
新增 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
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",
],
}
评论区精华
本 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)。
风险与影响
- 风险:
- 外部 runner 依赖:PR body 明确指出合入前提是 b200-oma-8gpu-0 已在线(已确认)。但若该 runner 后续下线或标签缺失,schedule 触发的 nightly cron 对
skipped_stages 为空,会持续排队一个无人认领的 ["b200","8gpu"] job,造成 CI 挂起。
- 零测试覆盖空洞:当前没有任何启用的测试注册到 stage-c-8-gpu-b200,stage 收集零测试并以 0 退出,属于有意设计。真正的执行验证(sm100 上的 torch/cuda 兼容、BF16 matmul、容器内 ray/torchrun 启动)要等链路第 5 个 PR(b200-ci-enable-tests)才发生,在此之前 b200 路径从未被真实 job 跑过。
- 资源利用率:不分区意味着 2/4-GPU 的 Blackwell 测试会空闲 4-6 张 GPU;单分片 job 串行化 shard,若后续 Blackwell 测试量增长超出 job 超时预算,会需要重新引入分区矩阵或并发 runner。
- 镜像与硬件兼容性:验证了 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 新硬件平台
关联脉络
- PR #2768 [AMD] fix(docker): drop the obsolete ROCm Megatron fused-kernels patch: 两个 PR 共享 tests/ci/test/test_run_suite.py,属于同一套 CI stage 治理/锁测试机制的连续演进;2768 从 AMD 侧调整 stage 相关验证,2700 从 Blackwell 侧扩展 stage 体系。
- PR #2813 feat(ci): add user allowlists for command tiers: 同为 CI 基础设施治理方向,扩展 .github/workflows 与 tests/ci 工具链,反映仓库对 CI 权限与 runner 编排的持续投入。
- PR #2773 ci: default a file run to the PR's own image: 与 file_run.py 的 suite→runner 映射同属 CI 文件运行链路(run-ci-file.yml / resolve-file-run),本 PR 让该链路对 b200 suite 可见。
参与讨论