news 2026/9/14 19:55:52

Megatron-LM CI/CD 全指南:流水线结构、PR 测试标签与内部 GitLab CI 触发排查

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Megatron-LM CI/CD 全指南:流水线结构、PR 测试标签与内部 GitLab CI 触发排查

Megatron-LM CI/CD 全指南:流水线结构、PR 测试标签与内部 GitLab CI 触发排查

【免费下载链接】Megatron-LMOngoing research training transformer models at scale项目地址: https://gitcode.com/GitHub_Trending/me/Megatron-LM

Megatron-LM(NVIDIA 的 Megatron Core 大规模 Transformer 训练框架)在仓库内维护了一套完整的分层 CI/CD 体系:GitHub Actions 工作流根据 PR 标签动态决定测试范围、重复次数与容器镜像,同时提供tools/trigger_internal_ci.py把本地分支推送到内部 GitLab 并触发功能测试流水线。本文以 skills/mcore-cicd/SKILL.md 为主线,结合 .github/workflows/cicd-main.yml、tools/trigger_internal_ci.py 及 tools/trigger_internal_ci.md 等源码级证据,系统讲解:CI 流水线如何分层、各 PR 标签究竟控制什么参数、如何安全触发内部 GitLab CI、以及 CI 失败时如何从日志 artifact 中定位根因。读完本文,你将能正确地为自己的 PR 选择测试标签、安全地触发内部流水线,并独立完成一次 CI 失败的排查闭环。


一、Answer-First:先记住这套 CI 事实速查表

Megatron-LM 的 CI 对“该跑什么测试”的决策完全由PR 标签(label)驱动。SKILL 文档要求在任何涉及标签或触发的问题上,优先给出精确值,而非长篇解释。速查如下:

场景scopen_repeatlightweight
无任何标签mr-github-slim2false
Run testsmr-github1true
Run functional testsmr-github5false
合并队列(merge group)mr-github1false(自动,无需标签)

三个正交附加标签:

标签作用
container::lts仅把容器镜像路径切换为 LTS(长期支持版)NGC PyTorch 基础镜像,而非 dev 最新版——它是一次向后兼容性检查,不改变测试集,可与任意 scope 标签组合。必须显式 opt-in:只有当用户明确要求做 LTS 验证时才附加,即使是容器或依赖变更,也不要主动添加
Run MBridge tests额外触发 MBridge(Megatron-Bridge)L1 测试套件
Run NeMoRL tests额外触发 NeMo RL 的 Megatron 功能测试套件

⚠️破坏性远程写入警告tools/trigger_internal_ci.py会把当前分支**强推(force-push)**到内部 GitLab 远端上的pull-request/<branch>引用。任何情况下都必须先以--dry-run运行并确认目标引用,才能不带该标志调用;绝不针对共享分支或受保护分支运行,只允许指向你自己的 PR 分支。安全预检命令:

python tools/trigger_internal_ci.py --gitlab-origin gitlab --dry-run

只有在 dry-run 输出与预期目标一致后,才可添加可选的--functional-test-*标志。


二、CI 流水线结构:从 PR push 到最终 Gate

主工作流位于 .github/workflows/cicd-main.yml,其on触发器(第 16-23 行)包括:

  • push 到pull-request/[0-9]+分支(即 CI 分支,见下文第四节)
  • push 到deploy-release/*分支
  • merge_group事件(合并队列校验)
  • 每日schedule
  • 手动workflow_dispatch

同时工作流设置了concurrency组与cancel-in-progress: true,保证同一 head ref 的新 run 会取消旧 run。

整个流水线的 job 拓扑(源自 SKILL.md 的文本树,结合源码验证)如下:

is-not-external-contributor # SSO / 成员资格检查,决定 runner 与 maintainer 身份 └─ pre-flight # 复用 NVIDIA-NeMo FW-CI-templates 的预检,判定 docs_only / ci_workload 等 └─ configure # 核心决策节点:读取 PR 标签,产出 scope / container tag / n_repeat / cadence ├─ linting # autoformat.sh 检查 + golden values 校验 + 内核变更确定性覆盖检查 ├─ cicd-container-build │ ├─ cicd-parse-unit-tests → cicd-unit-tests-latest # 单元测试矩阵 │ ├─ cicd-parse-integration-tests-h100 → cicd-integration-tests-latest-h100 │ └─ cicd-parse-integration-tests-gb200 → cicd-integration-tests-latest-gb200 (仅 maintainer) └─ Nemo_CICD_Test # 最终 pass/fail 汇总门(汇总所有测试 job 结果并决定整体状态)

2.1configure:流水线的“大脑”

configurejob(cicd-main.yml)是理解整套机制的关键。它用一次gh pr view调用拉取 PR 的全部标签,然后按first match wins顺序决定参数:

if [ "$IS_MERGE_GROUP" == "true" ]; then SCOPE=L1; N_REPEAT=1; LIGHTWEIGHT=false elif [ "$HAS_RUN_TESTS" == "true" ]; then SCOPE=L1; N_REPEAT=1; LIGHTWEIGHT=true elif [ "$HAS_RUN_FUNCTIONAL" == "true" ]; then SCOPE=L1; N_REPEAT=5; LIGHTWEIGHT=false elif [ "$IS_CI_WORKLOAD" == "true" ] || [ "$EVENT_NAME" == "workflow_dispatch" ]; then SCOPE=L1; N_REPEAT=5; LIGHTWEIGHT=false else SCOPE=L0; N_REPEAT=2; LIGHTWEIGHT=false fi

这里有一个值得注意的映射:SKILL.md 中出现的mr-github-slim/mr-githubGitHub 侧的 legacy scope 名,在 tests/test_utils/python_scripts/recipe_parser.py 中被统一别名到新的L-tier 成本分级词汇表

L-tier含义legacy 别名
L0精简 PR 测试(最便宜)mr-github-slim
L1完整 PR / 合并队列测试mr-github
L2夜间测试nightly
L3周测试weekly

L0-smoke则是 GitLab 侧专用的亚 L0 层,用于轻量 smoke 测试(只做2步训练)。scope 是成本/套件标签,而触发轴由cadencepr/nightly/mergegroup/weekly)单独承担——测试 recipe 默认挂[pr, nightly, mergegroup]三种 cadence。

configure还会输出一套决策树摘要到 step summary,内容与 SKILL.md 的表格完全一致,并附上术语表:

  • lightweight:训练 4 步而非 100 步,跳过 golden values 对比——反馈更快,但不保证数值正确性
  • lts:使用 LTS 容器基础镜像替代最新的 dev 镜像
  • dev:默认,使用最新开发容器镜像
  • cadence:按触发事件过滤测试的维度(recipe 中的cadence:字段)
  • run_mbridge:是否触发 Megatron-Bridge 下游 CI,PR push 默认关闭,加Run MBridge tests标签开启
  • run_nemo_rl:是否触发 NeMo RL 下游 CI,合并队列校验默认跳过,PR 作者可加Run NeMoRL tests标签 opt-in

2.2 镜像构建与测试矩阵

cicd-container-build通过 .github/workflows/_build_ci_container.yml 复用构建镜像,容器镜像推送到:

  • AWS ECR:766267172432.dkr.ecr.us-east-1.amazonaws.com/…
  • GCP Artifact Registry:us-east4-docker.pkg.dev/nv-projdgxchipp-20260113193621/megatron-lm/…

单元测试与集成测试都是典型的parse → matrix模式:cicd-parse-*先用yq读取 tests/test_utils/recipes/h100/unit-tests.yaml 等 recipe 文件生成 JSON 矩阵,再由cicd-unit-tests-latest/cicd-integration-tests-latest-h100matrix.include并行展开。集成测试的 recipe 覆盖了 gpt、moe、mamba、hybrid、bert、t5、mimo、multimodal-llava、各类 inference server 等数十个用例(见 tests/test_utils/recipes/h100 目录)。

GB200 测试(cicd-*-gb200)额外受双重门控:is_maintainer == 'true'vars.ENABLE_GB200_TESTING == 'true'——非 maintainer 的 PR 默认不会触发 GB200 测试。

2.3Nemo_CICD_Test:最终状态汇总

Nemo_CICD_Test是整体 pass/fail 的收口 job:docs-only 与部署工作流直接放行;否则汇总单元测试、H100/GB200 集成测试结果,并用gh run view做全 job 扫描(排除merge-queue-notificationcicd-mbridge-testingcicd-nemo-rl-testing),任何 failure/cancelled job 都会导致整体失败。

2.4 单元测试划分与 cadence 过滤

单元测试矩阵来自 recipe 中的unit-tests.yaml,每个测试被切分为多个 bucket 并行执行;功能测试则通过 tests/test_utils/python_scripts/generate_jet_trigger_job.py 生成 GitLab 子流水线配置,其中--cadence参数透传给 tests/test_utils/python_scripts/recipe_parser.py 的load_workloads(),按pr/nightly/mergegroup过滤 recipe 行。Run tests/Run functional tests标签会置cadence_bypass=true,让贡献者可以绕过 cadence 过滤获得手动覆盖能力。


三、PR 测试标签选择指南:一张表搞定

SKILL.md 提供了按“变更性质”选标签的权威对照表,开 PR 时直接对号入座:

变更路径 / 性质应附加的标签
仅文档(docs/*.md、docstring)
仅 CI/工具链(.github/tools/Makefile
仅测试文件(tests/)——修改已有测试,未新增 golden valuesRun tests
新增测试用例(尚无 golden values)Run functional tests
重新启用被禁用的测试(scope-broken→ active)Run functional tests
非数值类库代码(日志、错误处理、CLI 标志、重构)Run tests
可能影响训练数值(模型结构、attention、优化器、分布式、MoE 路由)Run functional tests
容器或依赖变更(docker/pyproject.tomluv.lockRun tests(仅在用户明确要求 LTS 验证时再加container::lts
涉及 MBridge 集成追加Run MBridge tests
可能影响 NeMo RL 的 Megatron 集成追加Run NeMoRL tests

经验法则:默认使用Run tests;当 PR 新增测试用例(必须生成 golden values)或变更可能引起 loss 曲线偏移时,一律使用Run functional tests

这套决策与源码完全一致:linting job 中 cicd-main.yml 会对tests/functional_tests/test_cases/**/golden_values*.json的变更运行 tools/check_golden_values.py 校验;同时用 tools/check_kernel_determinism_coverage.py 强制内核(kernel)变更必须附带确定性测试——这正是“新增测试用例必须跑Run functional tests”在流水线层的体现。


四、触发内部 GitLab CI:先 dry-run,再触发

4.1 前置条件

tools/trigger_internal_ci.py的目标用户是 NVIDIA 内部成员(SKILL 文档注明仅对 NVIDIAN 有用),它可以在不触碰 GitLab UI 的情况下完成“推分支 + 触发流水线”。完整配置步骤见 tools/trigger_internal_ci.md:

1. 添加内部 GitLab 为 git remote:

git remote add gitlab git@<gitlab-hostname>:ADLR/Megatron-LM.git git remote -v # 检查已有 remote;注意:这个 origin 名之后会作为参数传入!

2. 获取 Personal Access Token:

  1. 打开内部 GitLab 个人资料:User menu → Edit profile → Access tokens
  2. 点击Add new token,填写描述、设置过期时间,并勾选apiscope
  3. 创建后复制生成的 token(以glpat-开头)
  4. 存入环境变量,避免每次手动传参:
export GITLAB_TOKEN=glpat-<your-token>

建议将该变量写入.env.bashrc

4.2 安装依赖与用法

python -m pip install python-gitlab python tools/trigger_internal_ci.py \ --gitlab-origin gitlab \ [--access-token glpat-<your-token>] \ [--functional-test-scope mr] \ [--functional-test-repeat 5] \ [--functional-test-cases all] \ [--functional-test-name release-testing/mcore-vX.Y.Z] \ [--functional-test-time-limit 14400] \ [--dry-run]

参数对照表(来自 tools/trigger_internal_ci.md):

参数默认值说明
--gitlab-origin必填指向内部 GitLab 的 git remote 名
--access-token$GITLAB_TOKENapiscope 的 Personal Access Token
--functional-test-scopemrFUNCTIONAL_TEST_SCOPE流水线变量
--functional-test-repeat5FUNCTIONAL_TEST_REPEAT流水线变量
--functional-test-casesallFUNCTIONAL_TEST_CASES流水线变量
--functional-test-namecommit SHAFUNCTIONAL_TEST_NAME流水线变量——为pre-release/releasescope 的 run 命名(用作 run 名与 W&B 实验名)
--functional-test-time-limit随 scope 而定FUNCTIONAL_TEST_TIME_LIMIT流水线变量(秒)。release/weekly长时运行 scope 默认14400(4 小时),其余 scope 不设置
--dry-run关闭只打印将要执行的操作,不推送、不触发

release 测试请使用--functional-test-scope release,并用release-testing/mcore-v<X.Y.Z>约定命名 run(例如release-testing/mcore-v0.17.0)。

4.3 脚本真实执行流程

从 tools/trigger_internal_ci.py 源码可以看到完整调用链(main(),第 136-255 行):

  1. 校验 token--access-tokenGITLAB_TOKEN缺失则直接报错退出(第 209-211 行)
  2. 获取当前分支git rev-parse --abbrev-ref HEAD(第 89-97 行)
  3. 解析 GitLab 主机名:从 remote URL 中提取(兼容git@SSH 与 HTTPS 两种格式,第 80-86 行)
  4. 构造目标引用pull-request/<branch>(常量GITLAB_BRANCH_PREFIX = "pull-request",第 36 行)
  5. 强推分支git push <origin> HEAD:pull-request/<branch> --force(第 100-110 行;--dry-run时只打印日志)
  6. 组装流水线变量并触发:固定写入UNIT_TEST=noINTEGRATION_TEST=no,再叠加FUNCTIONAL_TEST_SCOPE/REPEAT/CASES,以及可选的FUNCTIONAL_TEST_NAMEFUNCTIONAL_TEST_TIME_LIMITCLUSTER_A100/H100/GB200;最终通过python-gitlab在项目 19378 上创建 pipeline(第 113-133 行)

脚本内部还包含一个细节:resolve_time_limit()(第 51-66 行)只在release/weekly两个长时 scope 下自动注入 4 小时上限,其余 scope 保持默认,避免为短时测试施加不必要的超时限制。

4.4 预期输出

Current branch: my-feature-branch Everything up-to-date Triggering pipeline on https://<gitlab-hostname> project 19378 @ pull-request/my-feature-branch Pipeline triggered: https://<gitlab-hostname>/<namespace>/<project>/-/pipelines/123456

对应 SKILL.md 的约束:只针对你自己的 PR 分支操作,绝不触碰共享/受保护分支。当触发 GitLab 功能测试时,子流水线由generate_jet_trigger_job.py生成:它读取 recipe、按 model 分 stage、为每个 test_case 生成一个 GitLab job,并支持--enable-lightweight-mode(2 步 smoke 测试)、--enable-warmup(首个 job 作为后续 job 的缓存预热依赖)等开关。


五、CI 失败排查:从分支名到根因的完整链路

CI 分支永远遵循pull-request/<number>命名模式,这是所有排查的起点。

5.1 从 CI 分支定位 PR

# 从当前分支提取 PR 号 PR_NUMBER=$(git rev-parse --abbrev-ref HEAD | grep -oP '(?<=pull-request/)\d+') # 查看 PR 元数据(标题、标签、作者、基础分支) gh pr view "$PR_NUMBER" --repo NVIDIA/Megatron-LM # 查看该 PR 的变更集 gh pr diff "$PR_NUMBER" --repo NVIDIA/Megatron-LM

5.2 读取 CI Job 日志

# 列出该 PR 最近的 workflow run gh run list --repo NVIDIA/Megatron-LM --branch "pull-request/$PR_NUMBER" # 流式输出失败 job 的日志 gh run view <run-id> --repo NVIDIA/Megatron-LM --log-failed

关键点:各 rank 的完整日志不在runner 的 stdout 里,而是作为 GitHub artifacts 上传,命名格式为logs-<test_case>-<run_id>-<uuid>

# 1. 先查出 artifact 名称 gh run view <run-id> --repo NVIDIA/Megatron-LM --json artifacts \ --jq '.artifacts[].name' # 2. 下载 artifact zip gh run download <run-id> --repo NVIDIA/Megatron-LM \ --name "logs-<artifact-name>" -D ./ci-logs # 3. 定位哪些 rank 日志含有错误 grep -r -l "ERROR\|Traceback\|FAILED\|fatal" ./ci-logs/ # 4. 日志文件可能超过 10000 行——永远不要一次性读完整份日志 wc -l ./ci-logs/<test>/<attempt>/attempt_0/<rank>/stderr.log sed -n '1,200p' ./ci-logs/.../stderr.log # 分段读取

5.3 按失败类型定位根因

SKILL.md 给出五类典型失败的处理路径:

  1. Linting 失败—— 本地重跑tools/autoformat.sh,diff 会精确显示需要修改的内容(该脚本在 linting job 中以CHECK_ONLY=true运行,见 cicd-main.yml)
  2. 容器构建失败—— 检查cicd-container-buildjob 日志
  3. 单元测试失败—— 失败的 bucket 位于cicd-unit-tests-latestjob 的 matrix 中
  4. 功能测试失败—— 查看cicd-integration-tests-*job,从rank 0 的stdout.log开始
  5. Flaky 测试—— runner 会自动重试至多 3 次;若重试耗尽且错误模式匹配已知的瞬时问题(NCCL、ECC、segfault),则属于基础设施噪声

5.4 将失败与 PR 变更集关联

# 找出覆盖了被改源码文件的单元测试 grep -r "from megatron.core.transformer.attention" tests/unit_tests/ -l # 查看 CODEOWNERS 确认 reviewer 分配 cat .github/CODEOWNERS | grep "<changed-path>"

.github/CODEOWNERS(位于仓库 .github 目录下)是确认各路径责任人的权威来源;结合gh pr diff输出的变更文件清单,即可快速圈定最可能受影响的测试模块与需要拉入 review 的人。


六、实践要点与避坑清单

  • 先答事实,再讲道理:问标签选什么、触发什么参数时,直接给出第一节速查表中的精确值,这是仓库 CI 文档的第一原则。
  • container::lts是 opt-in:无论改动是否涉及容器/依赖,都不应主动附加该标签,除非用户明确要求做 LTS 兼容性验证。
  • dry-run 是铁律tools/trigger_internal_ci.py每次真实执行都是一次对pull-request/<branch>的 force-push,务必先跑--dry-run核对目标引用,且只作用于自己的 PR 分支。
  • 数值型变更默认Run functional tests:凡是可能影响 loss 曲线的改动(模型结构、attention、优化器、分布式、MoE 路由),都应触发 5 次重复 + golden values 对比的完整功能测试;仅日志/CLI/重构等非数值变更用Run tests(1 次重复、轻量模式)即可。
  • 日志分段读取:单份 rank 日志可能超过一万行,务必先用wc -l探明规模,再sed分段查看,避免一次读取吞掉上下文。
  • 理解参数在源码中的落点scope/n_repeat/lightweight三个值最终经由 recipe_parser.py 的 scope 别名与 cadence 过滤,映射到具体的 recipe 测试行;阅读 tests/test_utils/recipes/h100 下的 YAML 可以精确预判“这个标签组合实际会跑哪些用例”。

参考文件速览

  • 技能文档:skills/mcore-cicd/SKILL.md
  • 主工作流:.github/workflows/cicd-main.yml
  • 容器构建工作流:.github/workflows/_build_ci_container.yml
  • 触发脚本:tools/trigger_internal_ci.py 与配置说明 tools/trigger_internal_ci.md
  • recipe 解析:tests/test_utils/python_scripts/recipe_parser.py
  • GitLab 任务生成:tests/test_utils/python_scripts/generate_jet_trigger_job.py
  • 测试 recipe:tests/test_utils/recipes/h100(含 unit-tests.yaml 与各模型功能测试用例)
  • 校验工具:tools/check_golden_values.py、tools/check_kernel_determinism_coverage.py、tools/autoformat.sh
  • 代码归属:.github/CODEOWNERS

【免费下载链接】Megatron-LMOngoing research training transformer models at scale项目地址: https://gitcode.com/GitHub_Trending/me/Megatron-LM

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 19:55:43

后端工程师三天速成前端三件套:AI辅助下的高效学习路径

很多后端同学跑来问我同一个问题&#xff1a;前端三件套到底怎么学&#xff1f;以前我带人上手HTML、CSS、JavaScript&#xff0c;最快也要两三个月&#xff0c;中间还得折腾一堆构建工具、框架概念&#xff0c;很多人没到写页面就先放弃了。现在情况确实不一样了&#xff0c;A…

作者头像 李华
网站建设 2026/9/14 19:54:15

SpringBoot+Vue+MyBatis+MySQL汽车销售网站系统全栈实战解析

做了好几个月的汽车销售管理类项目&#xff0c;这次这套基于SpringBootVueMyBatisMySQL的靓车汽车销售网站系统算是我觉得最能直接拿来复用的产物。整个系统覆盖了常见的商用场景&#xff1a;用户端看车、搜车、看视频、预约试驾、在线询价&#xff0c;管理端负责车辆上下架、分…

作者头像 李华
网站建设 2026/9/14 19:54:11

智驾芯片竞争本质:不是算力排行榜,而是工程确定性之战

1. 英伟达不是“王座”&#xff0c;而是整个智驾芯片生态的底层操作系统“谁能撼动英伟达王座&#xff1f;”——这个提问本身&#xff0c;就暴露了对当前智能驾驶芯片格局最典型的认知偏差。我从2018年参与第一代L2域控制器量产项目起&#xff0c;就反复在内部技术评审会上强调…

作者头像 李华
网站建设 2026/9/14 19:54:11

GEO与SEO/SEM差异解析及地理引擎优化实战

1. GEO与传统SEO/SEM的本质差异解析GEO&#xff08;地理引擎优化&#xff09;与传统SEO/SEM的根本区别在于目标维度的不同。传统SEO/SEM主要解决"如何在搜索引擎结果页获得更好排名"的问题&#xff0c;而GEO要解决的是"如何在地理空间维度上获得更精准的流量分发…

作者头像 李华
网站建设 2026/9/14 19:54:02

Go map 扩容机制:渐进式迁移如何实现均摊 O(1)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华