mvp v1 finish, 跑通docker 3容器ppo on ray cluster
BIN
specs/assets/arch.png
Normal file
|
After Width: | Height: | Size: 5.2 MiB |
BIN
specs/assets/layout.png
Normal file
|
After Width: | Height: | Size: 5.2 MiB |
BIN
specs/assets/networking.png
Normal file
|
After Width: | Height: | Size: 5.6 MiB |
BIN
specs/assets/node_bootstrap.png
Normal file
|
After Width: | Height: | Size: 5.6 MiB |
BIN
specs/assets/node_onboarding.png
Normal file
|
After Width: | Height: | Size: 5.1 MiB |
BIN
specs/assets/scheduling.png
Normal file
|
After Width: | Height: | Size: 5.8 MiB |
BIN
specs/assets/task_submit.png
Normal file
|
After Width: | Height: | Size: 5.6 MiB |
115
specs/hl_design_v2.md
Normal file
@@ -0,0 +1,115 @@
|
||||
# 基于Ray Cluster的overlay计算集群方案
|
||||
**“中心化控制平面 + 分布式计算平面”** 的架构设计。系统基于 **Ray Cluster** 构建应用层调度器,利用 **SSH** 作为带外(Out-of-Band)节点发现机制,并在底层通过 **NFS** 实现数据一致性。
|
||||
|
||||
### 0\. 算力平台资源
|
||||

|
||||
算力平台上可以申请单节点容器(有无GPU均可)以及分布式任务下多节点容器。
|
||||
|
||||
初步设想,在同一个用户账户下预先申请一批分布式任务节点以及一批不同规格(GPU数量)的计算容器,
|
||||
并将这些计算容器全部纳管在一个CPU容器中的服务程序下,提供统一的访问入口,供云桌面多用户使用。
|
||||
|
||||
以下是该方案的**技术架构规范说明**:
|
||||
|
||||
### 1\. 架构拓扑 (Architectural Topology)
|
||||
|
||||

|
||||
|
||||
系统采用 **Hub-and-Spoke (星型)** 拓扑结构,逻辑上划分为控制平面(Control Plane)和计算平面(Data Plane)。
|
||||
|
||||
* **控制平面 (Control Plane / Head Node)**
|
||||
|
||||
* 部署于 **CPU 容器**。
|
||||
* 承载 **Ray GCS (Global Control Store)**:负责集群元数据管理、任务调度表维护、Actor 寻址。
|
||||
* 承载 **API Gateway (FastAPI)**:对外暴露 RESTful 接口,封装 Job Submission API。
|
||||
* 承载 **Node Provisioner (Bootstrap Daemon)**:负责节点生命周期管理的守护进程。
|
||||
|
||||
* **计算平面 (Data Plane / Worker Nodes)**
|
||||
|
||||
* 部署于 **GPU 容器池**。
|
||||
* 运行 **Raylet**:负责本地资源(GPU/CPU/RAM)管理和 Task 执行。
|
||||
* 集成 **Object Store (Plasma)**:负责节点间共享内存对象传输。
|
||||
* **IB Interconnect**:配置 NCCL 环境变量,绕过 TCP 协议栈,直接利用 InfiniBand 进行 GPU 显存直连通信(RDMA)。
|
||||
|
||||
* **存储平面 (Storage Plane)**
|
||||
|
||||
* **NFS Protocol**:全节点挂载 `/mnt/shared`。
|
||||
* **Artifacts Repository**:统一存储 Codebase、Datasets、Checkpoints、Logs。
|
||||
|
||||
### 2\. 核心机制设计 (Core Mechanisms)
|
||||
|
||||
#### 2.1 节点发现与纳管 (Node Discovery & Bootstrapping)
|
||||
|
||||

|
||||
|
||||
采用 **SSH-based Side-channel Injection (SSH 侧信道注入)** 机制绕过 K8s 控制面限制。
|
||||
|
||||
* **触发机制**:Provisioner 接收目标节点 IP 及凭证。
|
||||
* **握手流程**:
|
||||
1. Provisioner 建立 SSH 连接 (TCP/22)。
|
||||
2. 注入 **Ray Runtime Config**,执行 `ray start --address=<HEAD_VIP>:6379`。
|
||||
3. 注入 **Custom Resources** (如 `{"node_id_xyz": 1}`) 用于后续的亲和性调度。
|
||||
* **状态同步**:Raylet 启动后通过 TCP 回连 GCS,建立长连接心跳。
|
||||
|
||||
#### 2.2 任务调度策略 (Scheduling Strategy)
|
||||
|
||||

|
||||
|
||||
系统针对不同负载类型,采用差异化的调度原语:
|
||||
|
||||
* **Type A: SFT Workloads (Job-Level Scheduling)**
|
||||
|
||||
* **调度模式**:**Driver-on-Worker**。
|
||||
* **资源原语**:使用 Ray Job Entrypoint 资源约束 (`entrypoint_num_gpus=8`)。
|
||||
* **调度逻辑**:
|
||||
1. API Server 接收请求,提交 Job 到 GCS。
|
||||
2. GCS 调度器执行 **Resource Matching**,寻找满足 GPU 数量及 Custom Resource (节点亲和性) 的 Worker。
|
||||
3. 将 Shell Command (`torchrun`) 下发至目标 Worker 的 Raylet 执行。
|
||||
* **进程模型**:`torchrun` 作为子进程运行,独占节点 GPU。
|
||||
|
||||
* **Type B: RL Workloads (Actor-Level Scheduling)**
|
||||
|
||||
* **调度模式**:**Driver-on-Head** (或 Driver-on-CPU-Worker)。
|
||||
* **资源原语**:使用 Ray **Placement Groups**。
|
||||
* **调度逻辑**:
|
||||
1. Driver 进程在 Head 节点启动。
|
||||
2. Driver 申请 Placement Group (例如:`{"CPU": 1}` for Controller, `{"GPU": 1} * N` for Rollout Workers)。
|
||||
3. GCS 将不同的 Actors 实例化到集群内的各个 Worker 节点。
|
||||
* **通信模型**:Controller 与 Workers 通过 gRPC (Ray Protocol) 交换控制指令;Workers 之间通过 NCCL (IB) 交换 Tensor 数据。
|
||||
|
||||
#### 2.3 网络通信规范 (Networking Specification)
|
||||
|
||||

|
||||
|
||||
* **Control Plane Traffic (TCP/IP)**
|
||||
|
||||
* 范围:Head \<-\> Worker,Worker \<-\> Worker (非 Tensor 数据)。
|
||||
* 端口:6379 (Redis/GCS), 8265 (Dashboard), 10000-65535 (Ephemeral Ports)。
|
||||
* 要求:容器间 Overlay 网络互通。
|
||||
|
||||
* **Data Plane Traffic (RDMA/IB)**
|
||||
|
||||
* 范围:Worker \<-\> Worker (DDP/FSDP 通信)。
|
||||
* 协议:NCCL over IB Verbs。
|
||||
* 配置:通过 `runtime_env` 注入 `NCCL_IB_HCA` 等环境变量,确保训练流量卸载至 IB 网卡,不占用 Overlay 网络带宽。
|
||||
|
||||
### 3\. 工作流序列 (Workflow Sequence)
|
||||
|
||||
#### 3.1 节点上线流程
|
||||
|
||||

|
||||
|
||||
#### 3.2 任务提交流程 (以 SFT 为例)
|
||||
|
||||

|
||||
|
||||
### 4\. 数据持久化与隔离 (Persistence & Isolation)
|
||||
|
||||
* **Runtime Environment Isolation**:
|
||||
* 利用 Ray 的 `runtime_env` 特性,在 Job 级别隔离 Python 依赖 (pip packages) 和环境变量。
|
||||
* 支持为每个 Job 指定独立的 `working_dir` (指向 NFS 上的特定版本代码库)。
|
||||
* **Log Persistence**:
|
||||
* Stdout/Stderr 重定向至 NFS 挂载路径 (`/mnt/shared/logs/{job_id}/`),实现无状态容器的日志持久化。
|
||||
|
||||
### 5\. 总结
|
||||
|
||||
该架构通过**应用层集群化 (Application-Layer Clustering)** 技术,在异构且受限的 K8s 容器环境之上,构建了一套**逻辑上的 HPC 集群**。它解耦了底层基础设施管理(由 SSH 负责)与上层计算任务调度(由 Ray 负责),是处理 Verl/SkyRL 此类强耦合分布式应用的标准化解决方案。
|
||||
120
specs/mvp/v1/mvp_plan.md
Normal file
@@ -0,0 +1,120 @@
|
||||
# MVP 计划(V1)
|
||||
|
||||
本文档目标:把当前“口述/实验记录”整理成**可复现、可验收**的 MVP 计划,并明确下一步最小闭环。
|
||||
|
||||
## 1. 背景与目标
|
||||
|
||||
我们要验证的最小闭环是:
|
||||
|
||||
1) 在“Head(CPU 容器)+ Worker(GPU 容器)”的 Ray Cluster 上,能够跑通一次 `verl` 的 PPO 训练。
|
||||
2) 训练所需的 **数据集 / 模型缓存 / 训练产物(checkpoint)/ 日志** 不落在容器临时文件系统里,而是落在**共享存储(NFS)**,容器重启后可继续使用。
|
||||
3) 所有步骤能写成一套**清晰命令/脚本**,新人可照着复现。
|
||||
|
||||
## 2. 环境与假设
|
||||
|
||||
- 机器:H20 机器(具体规格由算力平台提供)
|
||||
- 访问方式:通过 `ssh h1a` 远程登录(进入算力平台/宿主访问入口)
|
||||
- 容器:算力平台可申请 CPU 容器(对外暴露端口)与若干 GPU 容器(可 SSH 互通)
|
||||
- 共享存储:所有容器可挂载同一套 NFS(在 `specs/hl_design_v2.md` 中假设为 `/mnt/shared`)
|
||||
|
||||
## 3. 已验证现状(现有实验)
|
||||
|
||||
目录 `ray_in_docker/` 已经做过一次可运行的实验(偏“本地/示例级别”):
|
||||
|
||||
- 用 `docker-compose` 起了 2 个 `verl` 镜像容器:
|
||||
- `verl-head`:作为 Ray Head(Dashboard 端口 `8265`)
|
||||
- `verl-worker`:作为 Ray Worker
|
||||
- 在容器中执行:
|
||||
- 下载 GSM8K 数据集(`examples/data_preprocess/gsm8k.py`)
|
||||
- 拉取 HuggingFace 模型(示例:`Qwen/Qwen2.5-0.5B-Instruct`)
|
||||
- `ray start --head` + `ray start --address=...`
|
||||
- 通过 `ray job submit ... python -m verl.trainer.main_ppo ...` 提交 PPO 训练任务(见 `ray_in_docker/ray_example/ppo_train.sh`)
|
||||
|
||||
结论:**训练脚本可以跑通**。
|
||||
|
||||
## 4. 当前主要问题(从实验到平台化 MVP 的差距)
|
||||
|
||||
1) **数据 / 模型 / 输出落在容器内**:容器重启/替换后不可复用;也不利于多人共享与审计。
|
||||
2) **缓存路径不规范**:HuggingFace cache、Ray 临时目录、Hydra 输出目录等可能分散在容器默认路径。
|
||||
3) **可复现不足**:缺少明确的目录规范、统一的启动/提交流程、验收口径。
|
||||
4) Ray 节点**打标签/亲和性调度**的方法未固化:需要明确是否统一用 `ray start --resources`,以及命名规范如何设计。
|
||||
|
||||
## 5. MVP V1:最小闭环定义
|
||||
|
||||
以 `specs/hl_design_v2.md` 的方向为准,但 V1 **只做最小可运行原型**,暂不做完整 Web/调度系统。
|
||||
|
||||
### 5.1 目录规范(统一落到 NFS)
|
||||
|
||||
约定所有容器统一挂载 NFS 到 `/mnt/shared`,并在其中固定目录结构:
|
||||
|
||||
- `/mnt/shared/code/`:代码(可选:按版本/分支隔离)
|
||||
- `/mnt/shared/datasets/`:数据集(如 `gsm8k/`)
|
||||
- `/mnt/shared/hf/`:HuggingFace 缓存(设置 `HF_HOME=/mnt/shared/hf`)
|
||||
- `/mnt/shared/ray/`:Ray 运行期临时目录(可选:设置 `RAY_TMPDIR=/mnt/shared/ray/tmp`)
|
||||
- `/mnt/shared/outputs/`:训练输出根目录(Hydra/日志/ckpt 统一落这里)
|
||||
- `/mnt/shared/outputs/logs/<job_id>/`
|
||||
- `/mnt/shared/outputs/checkpoints/<job_id>/`
|
||||
|
||||
### 5.2 最小集群形态
|
||||
|
||||
- 1 个 Head(CPU 容器)
|
||||
- 跑 `ray start --head --dashboard-host=0.0.0.0`
|
||||
- 暴露 `8265` 给 Desktop/用户查看 Job 状态
|
||||
- 1~2 个 Worker(GPU 容器)
|
||||
- 跑 `ray start --address=<head_ip>:6379` 加入集群
|
||||
- (可选)通过 `--resources='{\"gpu_pool_a\": 1}'` 给节点打标签
|
||||
|
||||
### 5.3 最小训练任务
|
||||
|
||||
- 目标任务:跑通一次 `verl.trainer.main_ppo`(以 GSM8K 为例)
|
||||
- 要求:
|
||||
- `data.train_files` / `data.val_files` 指向 `/mnt/shared/datasets/...`
|
||||
- HuggingFace 模型下载缓存落到 `/mnt/shared/hf`
|
||||
- 训练输出(Hydra outputs、checkpoint、stdout/stderr)落到 `/mnt/shared/outputs/...`
|
||||
|
||||
建议在提交命令里显式覆盖 Hydra 输出目录(示例,具体目录名按需调整):
|
||||
|
||||
- `hydra.run.dir=/mnt/shared/outputs/logs/${JOB_TAG}`
|
||||
|
||||
## 6. 实施步骤(Checklist)
|
||||
|
||||
### 6.1 一次性准备
|
||||
|
||||
- [ ] 确认所有容器已挂载 NFS 到同一路径:`/mnt/shared`
|
||||
- [ ] 在 `/mnt/shared/` 下创建目录:`datasets/ hf/ outputs/ ray/`
|
||||
- [ ] 在所有容器中设置/注入环境变量(推荐写入统一脚本):
|
||||
- `HF_HOME=/mnt/shared/hf`
|
||||
- `HF_ENDPOINT=https://hf-mirror.com`(如需)
|
||||
- `RAY_TMPDIR=/mnt/shared/ray/tmp`(可选)
|
||||
|
||||
### 6.2 启动集群(Head + Worker)
|
||||
|
||||
- [ ] 在 Head 容器启动 Ray Head(并记录 `head_ip:6379`)
|
||||
- [ ] 在每个 Worker 容器执行 `ray start --address=...` 加入集群
|
||||
- [ ] 在 Head 上通过 `ray status` / Dashboard 验证节点已注册
|
||||
|
||||
### 6.3 准备数据与模型
|
||||
|
||||
- [ ] 数据集下载到:`/mnt/shared/datasets/gsm8k/`
|
||||
- [ ] 模型缓存落到:`/mnt/shared/hf/`(拉取一次即可多任务复用)
|
||||
|
||||
### 6.4 提交训练任务
|
||||
|
||||
- [ ] 用 `ray job submit --address=http://<head>:8265 ...` 提交 PPO 训练
|
||||
- [ ] 训练日志与 checkpoint 在 `/mnt/shared/outputs/` 可见
|
||||
|
||||
## 7. 验收标准(V1)
|
||||
|
||||
- [ ] Ray Head/Worker 能稳定加入同一集群(Dashboard 可见)
|
||||
- [ ] PPO 训练任务可提交并跑通(至少完成若干 step/epoch)
|
||||
- [ ] 数据集、HF 缓存、训练输出均在 `/mnt/shared/` 下可复用(容器重启后仍在)
|
||||
- [ ] 有一份“从零到跑通”的命令清单(或脚本)可复现
|
||||
|
||||
## 8. 未决问题(记录待补齐)
|
||||
|
||||
- [ ] Ray 节点标签/亲和性调度:是否统一用 `ray start --resources`,以及命名规范如何设计
|
||||
- [ ] RL workload 的 Driver 放置策略:先按 `verl` 默认即可,后续再按 `specs/hl_design_v2.md` 收敛到“Driver-on-Head / Placement Group”等模式
|
||||
|
||||
## 9. 下一步(进入 V2)
|
||||
|
||||
当 V1 达到“可复现 + 产物可落盘”的验收标准后,下一阶段工作见:`specs/mvp_plan_v2.md`。
|
||||
111
specs/mvp/v1/v1_action.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# MVP V1 远程实验行动文档(待确认后执行)
|
||||
|
||||
## 1. 任务复述(我理解的需求)
|
||||
|
||||
你希望我在远程机器 `argus@h1` 上,进入目录 `/home2/argus/infra/mvp`,把 MVP V1 的“原本流程”**手动完整跑一遍并验证**。要求:
|
||||
|
||||
1) 在宿主机上编写脚本,脚本通过 `docker exec` 在容器内执行命令,负责协调启动顺序(先 head、后 worker)。
|
||||
2) 集群拓扑改为:
|
||||
- 1 个 Ray Head:**没有 GPU**,并且 Head 的 Ray 资源 `CPU=0`(防止 Ray 把训练任务调度到 head)。
|
||||
- 2 个 Ray Worker:各自 **4 GPU**(总 8 GPU)。
|
||||
3) PPO 训练需要“轻量化”,把 `total_epochs` 改为 `1`。
|
||||
4) 先在本地仓库 `src/mvp/v1/` 写好脚本与 compose 文件;再拷贝到远程目录执行与验证。
|
||||
5) 在你确认这份行动文档没问题之前,我**不执行**远程操作。
|
||||
|
||||
## 2. 本地已准备的文件(在本仓库内)
|
||||
|
||||
- `src/mvp/v1/docker-compose.yaml`:3 容器(head + 2 worker),head 不使用 nvidia runtime;worker0/1 各限制 4 GPU。
|
||||
- `src/mvp/v1/scripts/`:宿主机脚本(内部全部用 `docker exec`)
|
||||
- `01_up.sh`:起容器
|
||||
- `20_start_head.sh`:启动 Ray head(`--num-cpus=0 --num-gpus=0`)
|
||||
- `21_start_workers.sh`:启动 Ray worker 加入集群
|
||||
- `30_prepare_data_and_model.sh`:准备 GSM8K 数据与预下载模型
|
||||
- `40_submit_ppo_epoch1.sh`:提交 PPO(`trainer.total_epochs=1`,并设置 `nnodes=2, n_gpus_per_node=4`)
|
||||
- `run_all.sh`:按顺序一键执行
|
||||
|
||||
## 3. 远程环境前置条件(需要你确认/保证)
|
||||
|
||||
在 `argus@h1` 上:
|
||||
|
||||
- Docker 可用,且有 `docker compose` 插件(Compose v2)。
|
||||
- NVIDIA runtime 可用(worker 容器需要 `runtime: nvidia`),宿主机有至少 8 张 GPU。
|
||||
- 不强制要求提前准备 `./verl`:脚本会在宿主机侧检查 `${PWD}/verl`,如果不存在会自动执行:
|
||||
- `git clone https://github.com/volcengine/verl.git`
|
||||
|
||||
此外本实验默认写入持久化目录:`/home2/argus/infra/mvp/shared`(会自动创建)。
|
||||
|
||||
## 4. 拷贝到远程(我执行前会再次征求你确认)
|
||||
|
||||
从本地(本机)同步到远程:
|
||||
|
||||
1) 同步脚本与 compose:
|
||||
- `rsync -av ./src/mvp/v1/ argus@h1:/home2/argus/infra/mvp/src/mvp/v1/`
|
||||
- `rsync -av ./specs/mvp/v1_action.md argus@h1:/home2/argus/infra/mvp/specs/mvp/v1_action.md`
|
||||
2) `verl/` 默认不需要同步(远程会 clone)。如果你更希望固定版本/避免网络波动,也可以手动同步:
|
||||
- `rsync -av --delete ./verl/ argus@h1:/home2/argus/infra/mvp/verl/`
|
||||
|
||||
## 5. 远程执行步骤(在宿主机上)
|
||||
|
||||
在远程机器执行:
|
||||
|
||||
1) 进入目录:
|
||||
- `cd /home2/argus/infra/mvp`
|
||||
2) 确保脚本可执行(首次同步后需要做一次):
|
||||
- `chmod +x ./src/mvp/v1/scripts/*.sh`
|
||||
3) 启动容器:
|
||||
- `./src/mvp/v1/scripts/01_up.sh`
|
||||
4) 安装 editable 版 `verl`(保证 `python -m verl...` 可用):
|
||||
- `./src/mvp/v1/scripts/10_install_verl_editable.sh`
|
||||
5) 启动 Ray Head(禁止调度到 head):
|
||||
- `./src/mvp/v1/scripts/20_start_head.sh`
|
||||
6) 启动两个 Ray Worker 加入集群:
|
||||
- `./src/mvp/v1/scripts/21_start_workers.sh`
|
||||
7) 准备数据 + 预下载模型(落到 `./shared`):
|
||||
- `./src/mvp/v1/scripts/30_prepare_data_and_model.sh`
|
||||
8) 提交 PPO(`total_epochs=1`,必须用 `ray job submit` 在 head 提交;通过 `--entrypoint-resources` 强制 driver 调度到 worker):
|
||||
- `./src/mvp/v1/scripts/40_submit_ppo_epoch1.sh`
|
||||
9) 观察状态:
|
||||
- `./src/mvp/v1/scripts/50_status.sh`
|
||||
- 打开 Ray Dashboard:`http://<h1宿主机IP>:8265`
|
||||
|
||||
也可以一键跑:
|
||||
- `./src/mvp/v1/scripts/run_all.sh`
|
||||
|
||||
## 6. 验收与验证点(执行时我会逐项检查)
|
||||
|
||||
1) Head 节点无 GPU:在 head 容器内 `nvidia-smi` 应不可用或无设备(worker 内可见 4 张)。
|
||||
2) Head 的 Ray 逻辑资源为 `CPU=0, GPU=0`:head 不应承载训练任务调度资源(通过 `ray start --num-cpus=0 --num-gpus=0`)。
|
||||
3) 集群节点数量正确:`ray status` 中应看到 1 head + 2 worker。
|
||||
4) PPO driver 不在 head:`ray job list` 里该 `submission_id` 的 `driver_info.node_ip_address` 应该是 worker 的 IP(`172.19.0.3/172.19.0.4`),不能是 head(`172.19.0.2`)。
|
||||
5) PPO 训练只跑 1 个 epoch:提交参数包含 `trainer.total_epochs=1`。
|
||||
6) checkpoint 落盘:`/mnt/shared/jobs/<job_id>/checkpoints/` 有产物(脚本通过 `trainer.default_local_dir` 强制指向该目录;不设置 `trainer.default_hdfs_dir`)。
|
||||
7) 数据与缓存落盘:`/home2/argus/infra/mvp/shared/` 下出现 datasets/hf/jobs 等目录。
|
||||
|
||||
补充(磁盘保护):
|
||||
- checkpoint 不要每步保存(会非常占空间);当前脚本默认 `trainer.save_freq=10`(每 10 step 保存一次)。
|
||||
|
||||
## 10. 目录命名约定(submission id)
|
||||
|
||||
- 脚本默认会显式指定 `ray job submit --submission-id=$SUBMISSION_ID`,并使用同一个值作为输出目录名:
|
||||
- 输出目录:`/mnt/shared/jobs/$SUBMISSION_ID/`
|
||||
- 你可以在提交时自定义 ID(推荐这样便于检索):
|
||||
- `SUBMISSION_ID=my_run_20251219_001 ./src/mvp/v1/scripts/40_submit_ppo_epoch1.sh`
|
||||
|
||||
## 7. 风险点与兜底
|
||||
|
||||
- 如果 `runtime: nvidia` 在该环境不生效:需要改成 compose 的 `gpus:` 写法(我会按远程 docker 版本调整)。
|
||||
- 如果 Ray Jobs 的 driver 必须在 head 启动(Ray 机制如此):这不影响“训练任务不调度到 head”,但 head 仍会有一个 job driver 进程。
|
||||
- 如果 `verl` 在镜像内已安装但版本不匹配:脚本会优先 `pip install -e /workspace/verl` 以保证行为一致。
|
||||
|
||||
## 8. 你需要确认的 3 个问题(你已确认,我按此执行)
|
||||
|
||||
1) `verl/`:脚本会在远程自动 `git clone https://github.com/volcengine/verl.git`(如你希望固定版本,可改成同步或 checkout tag/commit)。
|
||||
2) GPU:`0-7` 可用(worker0 用 `0-3`,worker1 用 `4-7`)。
|
||||
3) PPO:用满 8 GPU(`nnodes=2, n_gpus_per_node=4`)。
|
||||
|
||||
## 9. 你新增的关键要求(我已纳入脚本)
|
||||
|
||||
- 数据与模型必须落在 `/mnt/shared`(由宿主机 `./shared` bind mount 提供),并且具备**幂等**:
|
||||
- 数据:如果 `train.parquet/test.parquet` 已存在则跳过下载。
|
||||
- 模型:优先检测本地 cache(`HF_HOME=/mnt/shared/hf`);存在则跳过,否则才下载。
|
||||
- 提交 job 时显式注入 `HF_HOME/HUGGINGFACE_HUB_CACHE/TRANSFORMERS_CACHE`,确保训练使用持久化缓存与数据路径。
|
||||