4.9 KiB
4.9 KiB
MVP V1(Ray + VERL PPO)实验脚本
本目录用于在“宿主机 + Docker 容器”环境下,**用宿主机脚本(docker exec)**协调启动 Ray 集群,并通过 **ray job submit(在 head 提交)**跑通一次 verl 的 PPO 训练闭环(total_epochs=1),且数据/模型/日志/ckpt 都持久化到宿主机目录。
1. 运行环境与拓扑
1.1 依赖
- 宿主机:Linux
- 必需工具:
docker、docker compose(Compose v2 插件)、git - GPU:至少 8 张可用 GPU(索引
0-7),Docker 的 NVIDIA runtime 可用
1.2 集群拓扑(3 个容器)
mvp-ray-head(Ray Head)- 不挂 GPU(容器内
nvidia-smi不可用) ray start --head --num-cpus=0 --num-gpus=0:head 只做控制面,不参与计算调度- 暴露 dashboard:宿主机端口
8265
- 不挂 GPU(容器内
mvp-ray-worker-0(Ray Worker)- 4 GPU:
0,1,2,3 ray start ... --resources='{"worker_node": 100}'
- 4 GPU:
mvp-ray-worker-1(Ray Worker)- 4 GPU:
4,5,6,7 ray start ... --resources='{"worker_node": 100}'
- 4 GPU:
关键点:driver 不在 head
- 作业通过 head 提交:
ray job submit ... - 通过
--entrypoint-resources='{"worker_node": 1}'强制 entrypoint/driver 只能调度到 worker(head 没有该资源)
2. 持久化目录(宿主机 <-> 容器)
在宿主机项目根目录(运行脚本时的 ${PWD})下使用 ./shared 做持久化根目录,并 bind mount 到容器内 /mnt/shared:
- 宿主机:
./shared - 容器:
/mnt/shared
主要内容:
- 数据集:
/mnt/shared/datasets/gsm8k/ - HF 缓存:
/mnt/shared/hf/(脚本会设置HF_HOME,并尽量幂等跳过重复下载) - 每个 Ray Job 的输出(按 submission id 分目录):
/mnt/shared/jobs/<submission_id>/logs//mnt/shared/jobs/<submission_id>/checkpoints/
3. 整体流程(代码逻辑)
脚本都在 src/mvp/v1/scripts/,整体顺序如下:
00_prereq_check.sh- 检查
docker/docker compose/git
- 检查
05_ensure_verl_repo.sh- 若项目根目录下没有
./verl,自动git clone https://github.com/volcengine/verl.git
- 若项目根目录下没有
01_up.sh- 创建持久化目录(
./shared/...) docker compose up -d启动 3 个容器
- 创建持久化目录(
10_install_verl_editable.sh- 在 3 个容器内执行
pip install -e /workspace/verl(确保python -m verl...可用且代码与./verl同步)
- 在 3 个容器内执行
20_start_head.sh- 在
mvp-ray-head内启动 Ray head(CPU=0、GPU=0)
- 在
21_start_workers.sh- 在两个 worker 内启动 Ray worker 加入集群
- 同时给 worker 打
worker_node自定义资源标签
30_prepare_data_and_model.sh- 数据集:若
train.parquet/test.parquet已存在则跳过,否则生成 - 模型:使用 HF cache(
HF_HOME=/mnt/shared/hf),存在则跳过,不存在才下载
- 数据集:若
40_submit_ppo_epoch1.sh- 在 head 容器里执行
ray job submit - 显式指定
--submission-id=$SUBMISSION_ID - 通过
--entrypoint-resources='{"worker_node": 1}'强制 driver 在 worker - 训练参数:
trainer.total_epochs=1trainer.total_training_steps=29(GSM8K 该配置下对应 29 steps)trainer.save_freq=10(每 10 step 保存一次 checkpoint,避免磁盘爆炸)trainer.default_local_dir=/mnt/shared/jobs/$SUBMISSION_ID/checkpointshydra.run.dir=/mnt/shared/jobs/$SUBMISSION_ID/logs/hydra
- 在 head 容器里执行
50_status.sh- 打印
ray status/ray job list/ray job status/ray job logs | tail
- 打印
4. 运行方法
4.1 一键执行
在项目根目录执行:
./src/mvp/v1/scripts/run_all.sh
4.2 分步执行(推荐)
按顺序执行:
./src/mvp/v1/scripts/01_up.sh./src/mvp/v1/scripts/10_install_verl_editable.sh./src/mvp/v1/scripts/20_start_head.sh./src/mvp/v1/scripts/21_start_workers.sh./src/mvp/v1/scripts/30_prepare_data_and_model.shSUBMISSION_ID=ppo_h20_8g_$(date +%Y%m%d_%H%M%S) ./src/mvp/v1/scripts/40_submit_ppo_epoch1.sh./src/mvp/v1/scripts/50_status.sh
4.3 查看与停止
- Dashboard:
http://<宿主机IP>:8265 - 列出作业(在 head 容器内):
docker exec mvp-ray-head bash -lc "ray job list --address=http://127.0.0.1:8265"
- 停止某个 submission id:
docker exec mvp-ray-head bash -lc "ray job stop --address=http://127.0.0.1:8265 <submission_id>"
4.4 清理
- 停止并删除容器:
./src/mvp/v1/scripts/02_down.sh - 清理输出(谨慎,数据量可能很大):删除
./shared/jobs/<submission_id>/
5. 常见坑
- 不传
--submission-id会导致“输出目录难以等于 submission id”:因为 hydra/ckpt 目录需要在提交前确定。当前脚本会显式传--submission-id=$SUBMISSION_ID,并使用同名目录。 - checkpoint 太大:PPO 的 checkpoint 非常占空间。当前脚本默认
save_freq=10,如仍过大,可调大save_freq或减少保存内容/频率。
更多分步操作与验收标准见:specs/mvp/v1_action.md