
AI/ML 训练任务散落在本地机器上,难以复现和追溯。腾讯云云原生构建用 Pipeline/Stage/Job 三层结构把训练编排进流水线,通过 .cnb.yml 指定 GPU 节点跑训练、CPU 节点做数据准备,并沉淀模型产物,让训练可复现、可调度。
很多 AI 团队的训练还停留在"在自己机器上跑脚本"的阶段。谁跑、在哪跑、用了什么数据和参数,往往只有当事人清楚。时间一长,模型效果对不上、换台机器跑不通、复现结果靠运气,这些问题就冒出来了。
把训练任务放进 CI/CD 流水线,本质上是让训练过程也"代码化"。训练脚本、依赖环境、触发时机、产出产物都纳入版本管理,任何人提交代码都能触发同一套流程,得到可对比的结果。模型效果出现波动时,也能顺着流水线的记录往回定位是哪次改动、哪份数据引入的。
更重要的是,训练和验证不再依赖某台特定机器。任务被调度到云端 GPU 节点上执行,跑完产出模型文件或评估报告,沉淀到制品库。这样训练就从"个人手艺"变成了"团队可复用的标准流程"。
对 AI 团队来说,训练进流水线还能带来一个直接好处:每次代码变更都能自动跑一轮训练或验证,把"改代码—手动跑训练—看结果"这个循环压缩成"提交即验证"。迭代节奏更快,问题暴露也更早。
尤其是多人协作时,训练流水线相当于给每次改动都配了一道自动检查。谁动了模型结构、谁改了训练参数,提交后很快就能看到效果反馈,不用等人工排期跑训练。
CNB 的流水线采用 Pipeline/Stage/Job 三层结构。理解这三层,就能把一次训练拆成清晰的步骤。
Pipeline 是一次触发事件产生的完整执行过程,比如一次 push 或一次手动触发对应一条 Pipeline。Pipeline 通过 runner.tags 指定运行在哪类节点上(CPU 节点或 GPU 节点),整条 Pipeline 下的所有 Stage 共用同一个节点规格。Stage 是 Pipeline 里的执行阶段,多个 Stage 按顺序依次执行;同一个 Stage 内若声明了多个 Job,写成对象形式则并行执行、写成数组形式则串行执行。Job 是最小执行单元,在各自的 Docker 容器里运行。
映射到训练场景:数据准备、模型训练、效果评估可以分别做成三个 Stage 依次串行执行;而效果评估和模型打包这类互不依赖的步骤,可以放进同一个 Stage、用对象形式的 Job 并行跑。需要 GPU 算力的训练步骤,单独放在一条指定了 GPU 节点的 Pipeline 里,让算力用在刀刃上。
串并行的搭配很灵活。数据准备必须先完成,才能开始训练,所以 prepare 和 train 要串行;而训练产出的模型可以同时做效果评估和打包,这两步就能并行,从而缩短整条流水线的总耗时。
.cnb.yml 编排训练流水线下面是一条较完整的训练编排示例,覆盖数据准备(CPU)、模型训练(GPU)、效果评估(GPU)、产物打包(CPU)四个环节。由于 runner 是 Pipeline 级别的配置、对整条 Pipeline 的所有 Stage 生效,无法在同一条 Pipeline 里让不同 Stage 分别用 CPU 和 GPU 节点,因此这里按节点类型拆成两条 Pipeline:一条用 CPU 节点跑数据准备和打包,另一条用 GPU 节点跑训练和评估,两条 Pipeline 由同一个 push 事件触发、并行执行。
main:
push:
- name: train-cpu
runner:
tags: cnb:arch:amd64
cpus: 8
stages:
- name: prepare
script: |
python preprocess.py --input ./data --output ./processed
- name: package
script: |
python package.py --model ./ckpt/best.pt --output ./dist
- name: train-gpu
runner:
tags: cnb:arch:amd64:gpu
cpus: 16
stages:
- name: train
script: |
python train.py --data ./processed --epochs 10 --out ./ckpt
- name: eval-and-pack
script: |
python evaluate.py --model ./ckpt/best.pt --report ./report.json这条编排里,train-cpu Pipeline 用 8 核 CPU 节点,先做数据预处理、再在训练完成后打包模型;train-gpu Pipeline 调度到 GPU 节点,cnb:arch:amd64:gpu 提供 16 核 CPU 加 48GB GPU 显存,依次跑训练和效果评估。两条 Pipeline 由同一次 push 触发、并行推进,CPU 步骤与 GPU 步骤各跑各的节点。
把 CPU 和 GPU 步骤拆到不同 Pipeline 的好处是显而易见的:数据预处理这类 CPU 密集步骤不会占用昂贵的 GPU 时间,而训练和评估这类必须上 GPU 的步骤则集中在 GPU 节点上。整条流水线的成本因此被压到较低水平。
训练产出的模型文件可以进一步推送到 CNB 制品库,和代码版本关联起来,方便后续推理服务拉取或团队复用。所有节点最大运行时长为 18 小时,长时间训练也能容纳。
这两条 Pipeline 的触发事件都是 push,也就是每次代码推送到 main 分支都会跑一轮完整训练。如果只想在特定分支上训练,可以把 main 换成 glob 分支模式,为不同分支配置不同的训练任务。
训练任务不一定只在代码提交时触发。很多团队有每日重训、周期性回归的需求,可以用 schedule 事件做定时调度:
"dev/*":
schedule:
- cron: "0 2 * * *"
name: nightly-train
runner:
tags: cnb:arch:amd64:gpu
cpus: 16
stages:
- name: train
script: |
python train.py --data ./dataset --epochs 20 --out ./ckpt上面的配置在 dev/* 分支上每天凌晨 2 点触发一次完整训练。不同分支可以挂不同的训练任务,主干分支跑轻量验证、开发分支跑完整训练,互不干扰。GPU 节点按需占用、跑完释放,多个分支的训练任务在云端资源池里错峰执行。
定时调度对需要周期性产出模型的场景很实用,比如每日用新数据重训、每周跑一次全量回归对比效果。配合 schedule 的 cron 表达式,可以灵活定义触发节奏,让训练像定时任务一样稳定运行。
流水线跑通之前,训练脚本往往要先本地调试。CNB 的云原生开发同样支持 GPU 节点,可以在 .cnb.yml 的 vscode 事件里指定 GPU 标签,获得一个带 GPU 的云端开发环境,直接在里面调试训练代码,省去了本地配 CUDA 环境的麻烦:
$:
vscode:
- runner:
tags: cnb:arch:amd64:gpu
cpus: 16
services:
- vscode打开这个开发环境后,就能在浏览器或本地 IDE 客户端里连上云端 GPU 环境,边写边跑,确认脚本无误后再提交代码触发正式流水线。调试环境和流水线环境用的是同一套 GPU 节点规格,结果更一致。
这种"开发环境即流水线环境"的做法,能减少"本地能跑、流水线报错"的落差。训练脚本在云端 GPU 开发环境里调通后,提交触发流水线,跑出来的结果基本可预期,排查问题的范围也小得多。
训练进了流水线,还要保证"同样的代码能跑出同样的结果",流水线的记录才有追溯价值。有几个实操要点值得固定下来。
其一是锁定运行环境。每个 Job 都在指定的 Docker 镜像里运行,把深度学习框架、CUDA 版本、依赖库都固化进镜像,避免"这次能跑、下次换了基础镜像就报错"。镜像版本本身也可以打进制品库,和模型产物一起留存。
其二是固定随机种子与输入数据。训练脚本里把随机种子写死,数据预处理产出固定的输入集合并纳入版本管理,这样同一次提交触发的训练,结果才可对比、可复现。
其三是把关键参数显式记录。训练命令里的学习率、轮数、批大小等参数,直接写在 script 里而不是依赖外部默认值,让每次训练用了什么配置一目了然。配合流水线运行记录,一旦模型效果波动,就能顺着提交、参数、数据往回定位。
把训练任务调度进流水线,关键是想清楚"哪些步骤用 CPU、哪些步骤用 GPU、步骤之间如何串并联"。腾讯云 CNB 的 Pipeline/Stage/Job 三层结构配合 runner.tags 指定 GPU 节点,能把一次训练从数据准备到产物沉淀完整编排起来。想亲手编排一条训练流水线,可以到 腾讯云 CNB 对照 GPU 节点规格,从上面的示例改起,先跑通一个训练任务。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。