训练服务
HeteroFlow 是本站的异构算力与大模型调度产品。训练服务。训练服务 训练服务是 HeteroFlow 面向大模型微调与训练场景的托管能力:用户提交一份训练配置(框架、启动命令、超参、checkpoint 目录),平台负责多节点组调度、容器编排、日志与指标采集、产出文件管理、失败归因与用量核算。一次提交即可自动编排 N 节点 × 每节点…
训练服务
训练服务是 HeteroFlow 面向大模型微调与训练场景的托管能力:用户提交一份训练配置(框架、启动命令、超参、checkpoint 目录),平台负责多节点组调度、容器编排、日志与指标采集、产出文件管理、失败归因与用量核算。一次提交即可自动编排 N 节点 × 每节点 M 卡的训练组,完成 rank 分配、rendezvous 环境注入、分布式启动器校验与框架参数翻译,训练脚本无需感知集群细节。
训练服务与推理服务、普通容器任务同处一套统一调度体系:共享同一节点池、同一套租户隔离与权限模型、同一套可观测与用量核算基础设施。训练任务与推理任务可以共存于同一节点(训练可借用处于休眠状态的推理卡),租户配额、审计日志、失败聚类对训练全量生效;差异只在调度语义——训练组是静态 world、双向不参与抢占、以排队 + 优先级 FIFO 作为资源竞争方式。
功能总览
| 能力 | 一句话说明 | 状态 |
|---|---|---|
| 六框架适配 | ddp / deepspeed / fsdp / megatron / tensorflow / paddle,超参自动翻译为框架配置与环境变量 | megatron/ddp/deepspeed/fsdp 真机验证;tensorflow/paddle 实验性 |
| 静态 world 分布式编排 | n_nodes × per_node_gpu 一次成型,rank 拓扑与 MASTER 地址注入容器 | 已实现(含单节点真机) |
| 任务组生命周期 | pending → scheduling → running → completed/failed 全状态机与终态判定 | 已实现 |
| 组级故障处理 | 节点失联重排 / 混合活跃态判死 / rendezvous 挂死兜底 / 容器丢失服务端裁决 | 单节点组重排真机验证(65 秒完成重排) |
| Checkpoint 体系 | 白名单挂载、按框架完整性探测、断点续训两条路径、产出文件探测与下载 | FSDP 断点续训真机验证(loss 0.372 → 0.004 续跑收敛);Megatron 续跑真机验证 |
| 创建守卫 | 建组即 400 的 13 类硬规则 + 多机共享存储软告警,不静默吞错配 | 已实现 |
| 调度语义 | 训练双向不参与抢占、优先级 FIFO 排队、整组全有或全无绑定 | 已实现 |
| 超参注入 | 业务超参注入 HETEROFLOW_HP_<KEY> + HETEROFLOW_HYPER_PARAMS,建组即校验 | 已实现 |
| 训练镜像 | Megatron/TF/Paddle/HPC 构建配方,私有仓库凭证透传,大镜像节点内预热 | Megatron 真机验证;其余实验性 |
| 实时可观测 | 增量日志、TensorBoard 前端解析曲线、任务级 GPU 利用率、卡死检测 | 已实现 |
| 失败归因 | 11 类结构化失败分类落库,Dashboard 聚合分布 | 已实现 |
| GPU-秒计量 | 整卡独占计量、幂等结算、按人按租户统计 | 已实现 |
训练框架支持矩阵
平台不发明新的进程拉起方式:PyTorch 系框架由用户命令里自带的启动器(torchrun / python -m torch.distributed.run / deepspeed / accelerate launch)拉起;PaddlePaddle 用官方 python -m paddle.distributed.launch(或 fleetrun);TensorFlow 没有外部启动器,每节点一个进程,由 MirroredStrategy / MultiWorkerMirroredStrategy 驱动本机全部 GPU。框架差异只体现在平台注入的环境变量、生成的配置文件与显式校验上。
| 框架 | 平台编排产物 | 关键超参(被框架消费) | 专属校验 |
|---|---|---|---|
| ddp | 仅通用分布式环境变量 | 不消费任何超参 | 出现其它框架专属 key 即报错 |
| deepspeed | 生成 ds_config.json 落盘到 /tmp/heteroflow/,多机另生成 hostfile | ds_config、zero_stage、offload_optimizer、offload_param、gradient_accumulation_steps、train_micro_batch_size_per_gpu、bf16、fp16 | 未知 ds_ 前缀 key 报错;多机用原生 launcher 且未带 --no_ssh 拒绝 |
| fsdp | ACCELERATE_USE_FSDP + FSDP_* 环境变量 | fsdp_* 系列、mixed_precision | mixed_precision 限 no/fp16/bf16/fp8;布尔/正整数逐项校验 |
| megatron | MEGATRON_TP_PP_ARGS(拼好的 CLI 片段)+ 可 source 的 megatron_env.sh | tensor_model_parallel_size、pipeline_model_parallel_size | tp×pp ≤ world_size 且整除;异框架超参拒绝 |
| tensorflow | HETEROFLOW_TF_* 环境变量;多机按 rank 生成 TF_CONFIG | tf_distribution_strategy、tf_collective_implementation、tf_mixed_precision | 枚举白名单;多机 + mirrored 拒绝 |
| paddle | HETEROFLOW_PADDLE_*_DEGREE 环境变量 | paddle_mp_degree、paddle_pp_degree、paddle_sharding_degree、paddle_sharding_stage、paddle_amp_level | mp×pp×sharding ≤ world_size 且整除 |
三条边界如实说明:
- Megatron:官方脚本只认命令行参数,平台把 tp/pp 拼成
$MEGATRON_TP_PP_ARGS供启动命令直接引用(例:torchrun --nproc_per_node=$LOCAL_WORLD_SIZE pretrain_gpt.py $MEGATRON_TP_PP_ARGS --num-layers 24 …);模型结构等其余参数(num-layers / hidden-size / seq-length 等)平台没有信息来源,仍由用户在启动命令里自填。真实 Megatron 收敛训练已真机验证:TP=2 双卡收敛 + checkpoint 中断续跑。 - tensorflow / paddle / MPI / OpenMP:代码完成、镜像已构建并过 CPU 侧冒烟(TF 双 worker MWMS、Paddle 两容器 launch、nccl-tests 二进制齐全),GPU 真机训练未验证,标实验性。MPI 与 OpenMP 不是独立框架,挂在 ddp 下;跨节点 mpirun 不支持(容器间无 ssh/PMI)。
- 框架超参校验发生在调度期:建组照常返回成功,组在调度时校验白名单/互斥/并行度整除,不满足则整组标 failed(错误码
InvalidTaskGroupConfig),不会静默忽略——静默忽略就是"跑几小时才发现策略没生效"的事故源。
分布式编排:静态 World
训练组是静态 world:每节点一个容器、整卡独占、静态 rendezvous。判定逻辑收敛为唯一权威实现(IsStaticWorldGroup:task_type=training 一律是静态 world,与框架字段无关)。不追求运行中弹性是设计选择——DDP/DeepSpeed 的排他假设决定了 rank 拓扑必须在创建时一次写死,换来的是调度确定性与会话语义简单。
形状语义:提交时声明 n_nodes(节点数)与 per_node_gpu(每节点卡数),world_size = n_nodes × per_node_gpu 自动算出。调度器为组内每个 rank 绑定节点与卡组,rank 0 所在节点作为 master 地址源。
平台注入的分布式环境变量(训练脚本直接消费):
| 变量 | 值 |
|---|---|
MASTER_ADDR / MASTER_PORT | rank0 节点地址 / 按 groupID 哈希落在 20000–60000 的动态端口 |
NODE_RANK / NNODES / WORLD_SIZE / LOCAL_WORLD_SIZE | 节点下标 / 节点数 / 总进程数 / 每节点进程数 |
DIST_BACKEND | nccl;跨云时另注 CROSS_CLOUD=true + OWN_PUBLIC_IP(Gloo full mesh) |
HETEROFLOW_CHECKPOINT_PATH(恒为 /checkpoint)/ HETEROFLOW_DATASET_PATH(恒为 /dataset)等 | 训练配置投递 |
RANK / LOCAL_RANK | 仅单进程节点时注入;多进程场景交给 torchrun 推导 |
跨节点网络判定:同网络域可用内网 IP,跨 VPC / 地址冲突一律公网 + gloo——有内网 IP 不等于可用内网 IP。
GPU 精确授权:容器以 --gpus "device=N,M" 精确授权到卡,无卡组信息明确失败、绝不 all 兜底——客户按 N 卡付费就必须用到 N 卡,这是计量公平红线。agent 启动前另有一道卡组校验:卡组前缀、张数、唯一性任一不符即拒绝执行。
整组全有或全无:组调度的落地纪律是"要么整组绑定、要么整组回滚,不允许半绑定"——任一 rank 认领失败,已认领的全部放回 pending 重排,不会留下永远成不了 rendezvous 的残缺拓扑。
任务组生命周期与状态机
创建 → pending(排队)→ scheduling(组调度)→ starting → running
running → completed 容器退出码 0
running → failed 失败 + failure_class 结构化归因
running → stopping → stopped 用户停止,SIGTERM 优雅停止保留 checkpoint 收尾训练组的成员任务不走单任务自动重试(max_retries 设了也不生效):原地重启的 rank 加不进已成型的 rendezvous,failed 一律交组级流程接管。训练组失败后不会自动重建(与推理组不同,推理组由恢复流程自动重建完整 rank 集合)——训练有用户可见的成果语义与 checkpoint 续跑意图,平台代替用户决定"重跑一遍"会烧掉真金白银的卡时。恢复方式是用户重新提交整组;配置了断点续训时从最近 checkpoint 继续。
停止协议是统一状态机 running → preempting → stopping → stopped,容器收到 SIGTERM 优雅停止,保留 checkpoint 收尾时间。
故障处理
| 故障场景 | 处置 | 验证 |
|---|---|---|
| 节点失联 · 单节点训练组 | 心跳超 45s 判离线,成员迁回 pending,整组重排 | 真机验证:65 秒完成重排不卡死 |
| 节点失联 · 多节点组有幸存 rank | 混合活跃态静止满 5 分钟后整组判死(world 已成型,晚到 rank 永远加不进 rendezvous),错误信息写明恢复方式 | 已实现(逻辑由真实 PG 测试覆盖) |
| rank 崩溃、其余 rank 空等 | 周期检测(10s 一轮)发现后立刻把幸存 rank 置 stopping 释放 GPU、整组判 failed,不停在假 running | 已实现(单测 + 变异测试) |
| rendezvous 挂死 | 全部 rank running 但整组 GPU 持续零算力,10 分钟启动超时 + 2 分钟空转确认(约 12 分钟)判死;节点未上报利用率指标时该检查不生效,绝不靠猜杀任务 | 已实现 |
| 容器丢失 | agent 二次确认容器不在后上报事实,服务端裁决:集群还有在线节点就重置回 pending 重排,全灭才判 failed | 已实现 |
| 长期排不上队 | 排队超时兜底判 failed(训练走普通任务 30 分钟死线),时长锚点是最近一次写库时刻,老任务不会被误杀 | 已实现 |
失败原因聚类:任务失败时按 stdout/stderr 判据结构化归因落库,11 个分类——运行期 10 类(gpu_oom / host_oom / nccl_init / cuda_init / container_create / image_pull_transient / image_pull_permanent / user_code / user_entrypoint / unknown)+ 调度阶段专用 unschedulable(附结构化诊断 JSON,说明哪条过滤规则刷掉了多少节点)。Dashboard 按 classification 聚合展示失败原因分布,未知 key 原样透传不吞。
容错事件时间线:详情页展示每个 rank 的真实容错转移记录——节点失联迁回排队、断点续训注入(含注入的恢复路径)、GPU 卡丢失/恢复等,无事件时明确显示"暂无容错事件",不静默空白。
Checkpoint 体系与断点续训
存储与挂载:checkpoint_path 无条件挂载为每个节点容器内的 /checkpoint(宿主机路径须落在挂载白名单内:/data/、/tmp/heteroflow/、/home/*/heteroflow/、/opt/、/mnt/、/workspace/、/root/models/);dataset_path 挂载为 /dataset(只读)。
断点续训的两条路径:
1. 用户显式指定 resume_from_checkpoint——建组时做容器内可达性校验(只允许 /checkpoint、/dataset 及其子路径,或落在挂载白名单内),每次绑定时注入 HETEROFLOW_RESUME_FROM_CHECKPOINT,由训练脚本自行消费。注意显式值是固定路径,重排后重新启动仍从这个路径恢复,不会自动前进到更新的 checkpoint。
2. 自动续跑——用户未显式指定时,agent 在每次启动容器前(首次、失联迁移、重排、重新提交——所有路径同一入口)在 checkpoint 目录探测最新的完整 checkpoint 并注入同一变量。判定规则按框架区分:
| 框架 | 完整性证据(全部满足才算完整) |
|---|---|
| megatron | latest_checkpointed_iteration.txt 指向的 iter_* 目录存在、非空、无临时文件;缺记录文件不按 iter 号兜底 |
| deepspeed | latest 文件指向的 tag 目录:模型分片文件非空、无临时文件、ZeRO 分片编号从 0 连续且各组数量一致 |
| tensorflow | checkpoint 状态文件指向的前缀:.index 非空、.data-i-of-N 全部分片齐全 |
| ddp / fsdp | checkpoint-N 等目录内有平台完成标记 .heteroflow_complete,或 PyTorch DCP 的 .metadata |
| 任意框架兜底 | 训练脚本在 checkpoint 目录全部写完后(多 rank 时 barrier 后由 rank0)创建空文件 .heteroflow_complete |
探测带路径围栏:只看本任务声明的 /checkpoint 卷,宿主机路径及符号链接解析结果必须在节点挂载白名单内,记录文件里读出的名字必须是单段安全名——路径穿越、链接逃逸到别的任务/租户目录一律拒绝。单文件 checkpoint(*.pt 直接放根目录)无法判定是否写完,不作为候选。找不到可用 checkpoint 时不阻塞启动、从头开始训练,并如实记容错事件。
产出文件管理:详情页「实际产出文件(系统探测)」对 checkpoint 根目录发真实 list 请求,展示系统探测到的文件(名称/大小/修改时间),与用户手填的配置意图分开展示;每个文件可经 agent 文件通道分块上传、完整下载。真机验证数据:FSDP 断点续训任务在 checkpoint 恢复后 loss 从 0.372 续降至 0.004 收敛。
多机约束:多节点训练的 checkpoint_path 必须由共享存储(NFS / CephFS / 共享块设备)承载——平台无法验证这一点,只能在建组响应的 warnings 里软告警;若各节点各写本地盘,rank0 的 checkpoint 对其它 rank 不可见,resume 会无声失败。
创建守卫:建组即校验
配置错误的训练组代价极高(起容器、占卡、跑数小时才发现问题),因此创建入口执行硬校验,任一不满足返回 400 而不是静默忽略:
| 守卫规则 | 拒绝原因 |
|---|---|
training 块必填、framework 必填且在六框架白名单内 | 缺配置会在调度期解引用崩溃 |
checkpoint_path 必填且落在挂载白名单内 | 空值生成非法挂载参数;白名单外的卷会被静默丢弃,checkpoint 写进容器临时层、删容器即丢 |
per_node_gpu ≤ 8 | 超过单机物理上限的组永远匹配不到节点 |
三者都给时 world_size == n_nodes × per_node_gpu | 偏小的 world_size 会少记 GPU 配额 |
| 节点数必须可确定 | 显式 n_nodes,或 world_size 配合 per_node_gpu 反推 |
checkpoint_interval / max_runtime ≥ 0 | 负值此前被静默忽略 |
resume_from_checkpoint 必须容器内可达 | 不可达路径脚本 load 时 FileNotFound,而任务已按"成功"下发 |
| 多卡/多机命令必须自带分布式启动器 | 任一维度 >1 时命令须含 torchrun / torch.distributed / deepspeed / accelerate launch / paddle.distributed.launch / fleetrun;检测不到时可用 training.launcher 显式声明(合法取值 torchrun/deepspeed/accelerate/mpirun/custom);两者都没有才 400。没有启动器时多卡只用 1 张卡、多机各跑各的从不 rendezvous。tensorflow 多卡须声明 launcher=custom |
| 业务超参能无损注入容器 env | key 格式/长度、value 长度、个数、规整后不同名、不与环境变量抢名(详见超参注入一节) |
co_schedule 与 training 互斥 | 显存超分打包会撞 NODE_RANK 且忽略 per_node_gpu |
| 组名/任务名长度与控制字符、gpu_required ∈ [0,1024]、memory_mb 范围 | 通用字段范围校验 |
环境变量逐项 KEY=VALUE 且值无 NUL | HETEROFLOW_ 是平台保留前缀 |
| 多机训练挂节点本地卷拒绝 | 本地卷数据只在一台节点上,其它 rank 挂到的是空目录 |
此外有软告警(不阻断,写在创建响应 warnings 数组):多机训练组提醒 checkpoint_path 必须由共享存储承载。
任务列表与详情
训练页为列表/详情双栏:列表列名称、状态、GPU 数、节点(多节点按 rank 排序展开)、时长、提交时间,顶部另有运行中/已完成/失败统计卡片;支持按名称搜索(大小写不敏感子串)、提交时间与运行时长双键排序、状态筛选(排队中/运行中/抢占中/已完成/失败)。批量操作:全选 + 批量停止/批量删除(带进度提示);单组可停止、删除、克隆、一键部署推理。详情区纵向展示基本信息、资源配置(多节点按 rank 展开)、训练配置意图、系统探测产出文件、执行信息(镜像/卡型/提交人)、启动命令、容错事件时间线、错误信息(中文翻译在上、原文在下)与训练日志,空态与失败各有明确文案,不静默空白。
训练模板与历史克隆
- 内置框架模板 8 组:DDP 单机基线 / DeepSpeed ZeRO-2 / FSDP 全分片 / Megatron TP×PP=2×2 / TensorFlow MWMS 基线 / Paddle 数据并行基线 / MPI mpirun + NCCL tests / OpenMP 多线程——预填镜像、启动命令、启动器声明、环境变量与资源形状。应用模板会同步切换训练框架,且只覆盖未改动的字段。
- 历史克隆:训练列表任意状态的任务组均可克隆,全量配置回填创建页(自动剥掉平台注入的系统环境变量与命令包装、优先级反推回三档),修改后正常提交。
- 重新提交:详情页按钮,仅在 failed / completed 时出现,走克隆路径整组重跑——与自动重试是两回事(静态 world 组本来就不走单任务重试)。
调度语义与计量
双向不参与抢占(by design)
训练任务既不抢占别人也不被抢——训练成果不可丢,紧迫性判断会误判,抢占对训练是净损失。竞争方式 = 排队 + 优先级 FIFO(优先级三档:正常/高/最高)。两个方向各有一道独立的调度器防御:发起方按 task_type=training 直接跳过(防绕开任务组直接建高优先级单任务);victim 筛选对训练任务无论 preemptible 字段是什么值一律跳过(防直接改库)。单任务级 API 对 training + preemptible 组合另有 400 拒收。
静态拓扑不可变
训练组不支持任何形式的扩缩容:手动 scale、自动扩容、自动缩容、缩容开关由关改开四条路径全部 400——rank 拓扑创建时写死,事后加减副本会让幸存 rank 在下一次集合通信永久等待。
借用休眠推理卡(不是抢占)
训练调度候选节点空闲卡数不够、且缺口刚好 1 张时,若节点上有一张卡只被同租户(或共享租户组内核验)的 sleeping 状态推理任务占用(休眠已通过 vLLM sleep 真正释放物理显存),训练任务可直接借用这张物理卡——sleeping 任务的状态全程不动,不驱逐、不等待。边界:仅对 sleeping 生效;一张卡同一时刻只能被一个训练任务借用(数据库唯一约束);一个训练任务至多借 1 张。被借卡的推理服务收到唤醒请求时进入排队,训练结束自动唤醒。
计量与用量核算
- 口径:GPU-秒、整卡独占。GPU 数取每个 rank 任务自己的占卡数,组内求和即整组用量;建组时即按"每个 rank 实际占卡数之和"记配额(pending 期间配额占用就是真实值,不会偏低导致超额建组)。
- 幂等:结算写明细事件 + 按日聚合,认领进度快照做幂等标记,同一笔增量全局只记一次。
- 按人统计:租户用量查询含 per-user GPU 秒/小时;失败任务同样留痕。审计日志记录结构化资源用量(框架/卡数/节点数/卡型)。
超参注入
hyper_params 里的 key 分两类:
- 框架超参:被所选框架消费(deepspeed 的 zero_stage、megatron 的 tp/pp 等),翻译成框架配置文件/CLI 参数/编排环境变量,见框架矩阵一节。
- 业务超参:未被框架消费的 key(如
learning_rate、batch_size、num_train_epochs),注入每个 rank 的容器环境变量:
| 环境变量 | 内容 |
|---|---|
HETEROFLOW_HP_<NAME> | 单个业务超参的值。NAME = key 转大写、非字母数字替换为 _:learning_rate → HETEROFLOW_HP_LEARNING_RATE |
HETEROFLOW_HYPER_PARAMS | 全部业务超参的 JSON 对象,便于脚本一次读取;无业务超参时不注入 |
命名与覆盖规则:全部 rank 拿到相同的值;对 shell 形态命令、argv 直传命令、镜像自带 entrypoint 一律生效,命令不会被改写;业务超参不会覆盖平台注入的编排环境变量(超参 node_rank=99 只得到 HETEROFLOW_HP_NODE_RANK=99,NODE_RANK 仍是平台值);调度器对撞名另有显式防御。
校验(建组即 400):key 非空、≤64 字符、匹配 ^[A-Za-z_][A-Za-z0-9_.-]*$;value ≤4096 字节、不含 NUL;业务超参个数 ≤64;规整后不得同名(batch-size 与 batch_size 会撞同一个环境变量名,拒绝并点名);task.env 不得占用生成的环境变量名。
脚本读取示例:
import json, os
lr = float(os.environ["HETEROFLOW_HP_LEARNING_RATE"])
hp = json.loads(os.environ.get("HETEROFLOW_HYPER_PARAMS", "{}"))训练镜像
- 镜像不随产品内置:仓库提供构建配方(Megatron NGC 底座 / TF / Paddle / HPC-MPI),在 GPU 节点内经 kaniko 无特权构建后推内网 registry,或离线包分发;客户自带镜像亦可运行。
- 私有仓库凭证透传:任务对象里可带
image_pull_credential(registry/username/password 三元组),agent 拉取前任务级隔离 docker login,响应中密码一律脱敏——对标 K8s imagePullSecrets,镜像内容责任留在客户侧。 - 大镜像预热:10GB 级镜像超出任务态拉取预算,提供运维态主动拉取通道(2 小时预算 + 60 秒进度心跳判活);调度器不做镜像缺失自动补救,缺失任务直接失败并报明确原因。
监控与日志
- 增量日志:agent 每 10 秒一轮,首帧
docker logs --tail 2000整段替换、此后--since增量追加;抓取失败不推进时间窗口,宁可重复也不丢日志。两级截断:agent 侧单轮 1MB(头部截断并提示丢弃量)、server 侧累计 4MB(保留尾部);任务终态另有一条不截断的完整日志路径。前端 3 秒轮询、大小写不敏感搜索、一键下载。 - TensorBoard 指标曲线:对 checkpoint 目录发现 tfevents 文件 → 分块下载 → 前端直接解析 tfevents 二进制格式(自实现 TFRecord 帧格式、CRC-32C 校验与极简 protobuf reader,不引入后端 TF 依赖、不在节点跑 tensorboard 进程)→ 绘制 Loss/指标曲线 + 可展开数据表。前提是训练脚本真的写了 tfevents(写到
$HETEROFLOW_CHECKPOINT_PATH/tb_logs;Megatron 须显式传--tensorboard-dir)。 - 训练进度横幅:详情页顶部 Step / Loss / 相对更新时间——相对时间用 tfevents 里该 step 真正写入的 wall_time,不用"前端最近同步时刻"(后者会掩盖训练停滞)。
- 卡死检测:距最后一个 step 超 3 分钟且 GPU 利用率低于 5% 时显示"疑似卡住"告警;空态分三档明说(加载中 / 无 TensorBoard 日志 / 节点探测失败),不静默空白。
- GPU 监控:任务级 GPU 利用率历史曲线。
API 参考
POST /api/v1/task-groups(创建训练作业)
POST /api/v1/task-groups
{
"name": "llama-finetune-01",
"task_type": "training",
"training": {
"framework": "megatron",
"world_size": 4,
"n_nodes": 2,
"per_node_gpu": 2,
"checkpoint_path": "/data/ckpt/llama-ft01",
"checkpoint_interval": 600,
"hyper_params": {
"tensor_model_parallel_size": "2",
"pipeline_model_parallel_size": "2",
"learning_rate": "1e-4"
}
},
"task": {
"image": "registry/pytorch:2.3-cuda12.1",
"command": "torchrun --nproc_per_node=$LOCAL_WORLD_SIZE pretrain_gpt.py $MEGATRON_TP_PP_ARGS",
"gpu_required": 2
}
}training 对象字段(与后端 TrainingGroupConfig 逐字段一致):
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
framework | string | 是 | ddp / deepspeed / fsdp / megatron / tensorflow / paddle |
world_size | int | 条件 | 总进程数;须等于 n_nodes × per_node_gpu(三者都给时) |
n_nodes | int | 条件 | 节点数;节点数必须可确定(n_nodes / world_size ÷ per_node_gpu) |
per_node_gpu | int | 条件 | 每节点 GPU 数,上限 8 |
checkpoint_path | string | 是 | 宿主机路径,挂载为容器内 /checkpoint,须在挂载白名单内 |
checkpoint_interval | int | 否 | 自动保存间隔(秒),0 = 不自动保存 |
max_runtime | int | 否 | 最大运行时长(秒),0 = 不限制 |
resume_from_checkpoint | string | 否 | 恢复路径,须容器内可达 |
dataset_path | string | 否 | 宿主机路径,挂载为 /dataset(只读) |
hyper_params | map[string]string | 否 | 训练超参;框架 key 翻译为编排产物,其余注入容器 env |
launcher | string | 否 | 分布式启动器显式声明:torchrun / deepspeed / accelerate / mpirun / custom;命令字符串检测不到启动器时以此放行,未知取值 400 |
要点:
image/command/gpu_required必须嵌套在顶层task: {...}对象里,不是与training平级的顶层字段——顶层字段有严格白名单,写在错误层级 400 拒绝。command必填:entry_point字段不会被转成执行命令,缺失时容器空跑退出码 0(假成功)。hyper_params是 map,不是换行分隔字符串。- 成功响应在存在软告警时带
warnings数组。 - 权限:JWT
tasks:write或租户 API Key;member/viewer 角色仅见自己提交的训练组。
查询与详情
GET /api/v1/task-groups/{id}— 组配置、状态、组内任务列表(每任务含 rank / node_id / status / gpu_seconds_billed / failure_class)。GET /api/v1/task-groups/{id}/fault-events— 容错事件时间线(组级 + 全部 rank)。GET /api/v1/tasks/{id}/gpu-metrics— 任务级 GPU 利用率历史。GET /api/v1/tasks/stats— 含failure_breakdown失败聚类分布。
文件通道(checkpoint / 产出文件)
| 端点 | 用途 |
|---|---|
POST /api/v1/file-requests {task_id, request_type: "list"\|"download", target_path, offset_bytes?} | 创建对任务所在节点的文件请求(agent 异步执行) |
GET /api/v1/file-requests?task_id=X | 列出某任务的文件请求 |
GET /api/v1/file-requests/{id} | 轮询状态(completed 携带 entries / 分块元数据) |
GET /api/v1/file-requests/{id}/download | 下载类请求完成后流式取回完整文件 |
约束:target_path 必须是绝对路径、≤4096 字节、且必须落在该任务自己挂载的宿主机目录之内(按路径分段边界比对,挡 .. 逃逸与兄弟目录)——越界 400。分块只发生在 agent→server 上传段(默认 64MB/块),调用方拿到的是完整文件。
已知边界
1. Megatron 已真机验证的组合:TP=2 双卡收敛、checkpoint 中断续跑;TP×PP 组合并行与跨机 Pipeline Parallel 尚未真机验证(受硬件条件限制)。
2. TensorFlow / PaddlePaddle / MPI / OpenMP 代码完成、镜像 CPU 侧冒烟通过,GPU 真机训练未验证;国产卡暂无对应镜像;跨节点 MPI 不支持。
3. 训练组不支持任何扩缩容(静态 world 是设计选择);平台没有弹性训练(torchelastic)建模。
4. 日志搜索/下载基于已加载内容,超长日志受两级截断约束(agent 单轮 1MB、server 累计 4MB)。
5. AMD / 海光卡的容器隔离走 /dev/kfd + /dev/dri 设备直通,"精确 device 授权"这条保证只对 NVIDIA 路径成立。
6. 借卡关系(谁借了哪张休眠卡)后端有完整记录与约束,前端暂无展示;用户唤醒被借卡的服务时会收到中文排队提示。
7. checkpoint 完整性判定依据是框架/平台声明的完成证据 + 文件齐全,不反序列化权重内容;单个分片文件内容是否写完无法从元数据判断。
8. rendezvous 挂死检测刻意只覆盖"全部 rank running 且整组零算力"一种形态,混合态挂起(部分 rank 满载空转)漏检,由 30 分钟通用任务超时兜底。
<!-- 状态标注说明:本文各能力的状态口径如下——"真机验证"指在真实 GPU 节点上端到端运行并确认结果(含单节点组失联 65 秒重排、FSDP 断点续训 loss 0.372→0.004、Megatron TP=2 双卡收敛与中断续跑);"已实现"指代码合入且有单元测试 / 真实 PostgreSQL 集成测试覆盖,但未在真实 GPU 集群上端到端验证;"实验性"指代码与镜像完成、仅通过 CPU 侧冒烟验证,GPU 真机行为待验证。 -->