在百舸上使用 Wall-X 加速镜像训练 VLA 模型
概述
Wall-X 是视觉-语言-动作(VLA)模型:基座 Qwen2.5-VL-3B-Instruct,在 LIBERO single-arm 数据集上微调(wall-x v1.1.0 OSS + liberoall)。本加速镜像针对 RTX Pro 6000(P6k,单卡 ~97.9 GB)芯片做训练加速,已内置完整训练栈与优化后的训练脚本(一组 `WALLX_PERF*` 环境变量开关,工程等价为 torch.compile 重排 bf16 累加顺序,loss 曲线与 eager 一致)。不设任何开关时,镜像等价于原始版本(vanilla),优化必须显式开启开关;支持单机多卡与多机扩展训练。
本示例以 LIBERO(libero_all / single-arm)数据集为例,介绍在百舸平台上完成训练全流程。
适用场景
- 在百舸平台训练 Wall-X VLA 模型,用于机器人操作任务(LIBERO 等)
- 需要单机多卡训练,或多机扩展训练以获得更高吞吐的场景
- 需要断点续训、性能参考与常见问题指引的客户
环境与资源要求
| 项 | 内容 |
|---|---|
| 适配芯片 | 支持规格:aihc.lgn7ib |
| 源码 | 已内嵌于镜像 /root/workspace/wall-x(容器入口 WORKDIR=/root/workspace) |
| 软件栈 | NGC PyTorch 26.07-py3:Python 3.12.3 / torch 2.13.0a0(nv26.07 构建)/ CUDA 13.3,开箱即用 |
| 工作目录 | /root/workspace/wall-x |
| 数据集 | LIBERO(libero_all / single-arm),不打入镜像 |
| 模型权重 | Qwen2.5-VL-3B-Instruct + wall-x v1.1.0 OSS(model.safetensors),不打入镜像 |
在百舸平台准备训练环境
- 登录百舸平台,创建或进入开发机,选择 P6k 资源规格与上述加速镜像
- 打开开发机终端(或 WebIDE 终端),进入工作目录
/root/workspace/wall-x - 按本章节顺序下载数据与权重到统一根
/root/workspace/data(交付 config 已默认指向此目录,无需改路径),然后启动训练
准备数据集与权重
镜像不含数据/权重,部署时下载到统一根 /root/workspace/data(交付 config 已默认指向此,无需改路径)。
| 物料 | HuggingFace 地址 | BOS 地址 |
|---|---|---|
| LIBERO(libero_all / single-arm,数据集) | lerobot/libero | — |
| Qwen2.5-VL-3B-Instruct | Qwen/Qwen2.5-VL-3B-Instruct | bos://aihc-models-bj/Qwen/Qwen2.5-VL-3B-Instruct/ |
| wall-x v1.1.0 OSS(wall-oss-0.5) | X-Square-Robot/wall-oss-0.5 | — |
HuggingFace 为公开参考地址(内网可能不可达),实际下载以 BOS 为准。
参数说明
| 参数 | 值 | 说明 |
|---|---|---|
batch_size_per_gpu |
26(交付默认) | 优化版靠 WALLX_PERF_ALLOC 可稳定跑 bs26(~92 GB);baseline 对照无 ALLOC,需降到 bs≤20,否则 OOM |
num_workers |
16 | DataLoader worker 数 |
gradient_accumulation_steps |
1 | 不开梯度累积 |
use_fsdp |
false(DDP) | 交付口径走 DDP;WALLX_PERF_* 全开关仅在 DDP 路径生效 |
num_training_steps |
30(warmup 15) | 计时口径(正式训练按需调大);稳态取 step 15–29 |
优化配置接口
优化项由一组 WALLX_PERF_* 环境变量开关控制(=1 开启,不设置即默认关闭,不设任何开关时镜像等价于原始版本):
| 开关 | 说明 |
|---|---|
WALLX_PERF_ATTN |
强制 attn_deterministic=False(非确定 flash-attn) |
WALLX_PERF_ALLOC |
PYTORCH_CUDA_ALLOC_CONF=expandable_segments(减碎片,是本组开关省显存的主要来源) |
WALLX_PERF_DDP + WALLX_PERF_BUCKET |
重写 DDPStrategy.wrap,启用 static_graph + gradient_as_bucket_view + bucket_cap_mb(默认 100) |
WALLX_PERF_COMPILE / WALLX_PERF_COMPILE_VISUAL |
torch.compile 编译主干与视觉塔(配 WALLX_PERF_COMPILE_RECOMP_LIMIT=64) |
WALLX_PERF_NO_TIMER_BARRIER |
将 timer 的 barrier 置为 no-op(影响计时开销,不影响峰值显存) |
WALLX_PERF_LOG |
打印每个生效补丁一行日志,用于确认开关生效 |
推荐配置(优化开关,环境变量):
1export WALLX_PERF_ATTN=1
2export WALLX_PERF_ALLOC=1
3export WALLX_PERF_DDP=1
4export WALLX_PERF_BUCKET=100
5export WALLX_PERF_COMPILE=1
6export WALLX_PERF_COMPILE_VISUAL=1
7export WALLX_PERF_COMPILE_RECOMP_LIMIT=64
8export WALLX_PERF_NO_TIMER_BARRIER=1
9export WALLX_PERF_LOG=1 # 打印每个生效补丁一行日志,用于确认开关生效
注意:
COMPILE/COMPILE_VISUAL与DDP/BUCKET均在 DDP 路径(use_fsdp=false)内生效;FSDP 走另一 strategy、不经过该 wrap,compile 不会生效,故交付口径统一走 DDP。
启动训练
镜像内置两个启动脚本(位于 /root/workspace/wall-x/,仅差 WALLX_PERF_* 开关):run_wallx_optimized.sh(8 开关全开,交付优化口径)、run_wallx_baseline.sh(关闭全部开关,vanilla 对照)。二者自动识别卡数、支持多机(NNODES / NODE_RANK / MASTER_ADDR),共用 workspace/example/libero_local_perf.yml。
单机训练(8 卡)
1# 优化版(交付优化口径)
2bash run_wallx_optimized.sh
3
4# baseline(vanilla 对照)
5bash run_wallx_baseline.sh
多机训练(2 节点示例)
每台节点各执行一次并注入环境变量(rank0 先起):
1# node0(rank0)
2NNODES=2 NODE_RANK=0 MASTER_ADDR=<rank0内网IP> bash run_wallx_optimized.sh
3
4# node1
5NNODES=2 NODE_RANK=1 MASTER_ADDR=<rank0内网IP> bash run_wallx_optimized.sh
性能参考
以下数据为单机 8 卡 P6k(单卡 ~97.9 GB)实测,DDP,num_training_steps=30,稳态取 step 15–29。baseline = 同一镜像不设任何 WALLX_PERF_*(为真 vanilla),与优化版仅差「开关」这一个变量。
实测汇总(bs=26 交付口径,8 卡/机)
| 配置 | bs | 稳态步时 (s) | 吞吐 (samples/s) | 单卡峰值显存 | loss (iter1→5→10→20→29) |
|---|---|---|---|---|---|
| 单机 baseline(最大可行) | 20 | 0.877 | 182.5 | 93.1 GB | 0.299→0.245→0.177→0.123→0.104 |
| 单机 optimized | 26 | 0.859 | 242.1 | 91.5 GB | 0.301→0.248→0.173→0.116→0.103 |
| 双机 optimized 2×8 | 26 | 0.949 | 438.2 | 91.5 GB | 0.301→0.245→0.173→0.101→0.082 |
- 单机有效吞吐比 = 优化版@bs26 ÷ baseline@最大可行 bs20 = 242.1 / 182.5 ≈ 1.33×(优化版靠
WALLX_PERF_ALLOC吃下 bs26;baseline 无显存优化,bs22 起 OOM、最大只能 bs20) - 双机扩展比 = 438.2 / 242.1 ≈ 1.81×(并行效率 90.5%)
- 同为各自最大批时纯步时 ≈1.02×(bs26 计算 bound,优化收益主要来自"省显存 → 上更大 batch")
- loss 三者同批可比、收敛正常(双机 global batch 更大 26×16=416,末步 loss 更低)
batch size 扫描(优化版单机,DDP)
| bs/gpu | global batch | 稳态步时 (s) | 吞吐 (samples/s) | 单卡峰值显存 | 结果 |
|---|---|---|---|---|---|
| 16 | 128 | 0.682 | 188 | 71.6 GB | OK |
| 20 | 160 | 0.730 | 219 | 79.6 GB | OK |
| 24 | 192 | 0.797 | 241 | 87.5 GB | OK(留 ~7 GB 余量) |
| 26 | 208 | 0.859 | 242 | 91.5 GB | 交付默认(最大可稳定跑) |
| 28 | 224 | — | — | ~93.4 GB 后 OOM | OOM(iter1) |
优化分解(bs=16,实验环境计时)
| 里程碑 | 单步 (s) | 相对 baseline |
|---|---|---|
| baseline(原始版本) | 0.7677 | — |
| Phase 1(ATTN+ALLOC+DDP static_graph+BUCKET=100) | 0.7335 | −4.5% |
| +COMPILE(backbone) | 0.6960 | −9.3% |
| +COMPILE_VISUAL(最终版) | 0.6722 | −12.4% |
以上数据为特定测试环境下的参考值。实际性能会受到资源规格、数据读取方式、网络环境、任务参数等因素影响。
断点续训
支持断点续训(config 驱动、脚本不变)。在 workspace/example/libero_local_perf.yml 设置 checkpoint.resume_from,再照常启动脚本即可:
1checkpoint:
2 resume_from: /root/workspace/outputs/<训练输出>/<step目录> # 接续训练:指向 checkpoint 目录
3 # resume_from: /root/workspace/data/wall-oss-0.5/model.safetensors # 冷启动:只加载权重、从头计步
1bash run_wallx_optimized.sh # 与首训同一脚本,读到 resume_from 即自动续训(baseline 换 run_wallx_baseline.sh)
续训时状态(optimizer / scheduler / RNG / global_step)均可正确恢复;已修复上游「词表扩容 vs resume 顺序」崩溃(resume 时先按 checkpoint 词表 resize embedding,再建 optimizer / wrap DDP,compile-on / compile-off 两种崩溃模式均已消除)。
注意:续训与「不中断连续训练」非逐位一致(对齐位置 loss 差约 0.8–7%),源于 3 处上游保真度缺口(np_rng 未随 checkpoint 保存、global_step off-by-one、lerobot 无 mid-epoch 数据态),不影响正常接续收敛。
可复现性
镜像内置数据侧随机种子修复(DataCollator 的 np_rng + DataLoader worker 播种,带 rank 偏移)。vanilla(不开 compile / attn 非确定)下同参数多次训练,loss 与 grad_norm 逐位一致(rtol=1e-3 判据 PASS),可用于回归对齐;开优化开关时收敛一致、但不保证逐位。
参考
- 数据集 LIBERO:lerobot/libero
- Wall-X 开源权重(wall-oss-0.5):X-Square-Robot/wall-oss-0.5
- 基座模型:Qwen/Qwen2.5-VL-3B-Instruct
评价此篇文章
