|
| 1 | +# Run: Nemotron-3-Ultra 550B SWE-Teacher GRPO (cp16, 48× GB200) |
| 2 | + |
| 3 | +Clean runbook for the `swe_teacher_cp16` async-GRPO run on OCI-HSG (GB200, InfiniBand). |
| 4 | +Recipe: `examples/configs/ultra/swe_teacher_cp16.yaml` · Launcher: `swe_teacher_cp16_launch.sh`. |
| 5 | +(For root-cause / debugging history, see `SWE_TEACHER_CP16_REPRO.md`.) |
| 6 | + |
| 7 | +## TL;DR — run it |
| 8 | + |
| 9 | +```bash |
| 10 | +cd <repo-root> # the RL checkout on lustre |
| 11 | +# creds sourced on the LOGIN node only, never inside the compute container: |
| 12 | +source /lustre/fs1/portfolios/llmservice/projects/llmservice_nemo_reasoning/users/zhiyul/secrets.sh > >(grep -v HF_TOKEN) 2>&1 |
| 13 | +bash swe_teacher_cp16_launch.sh # submits a 48-node job via ultra_launch.sh -> ray.sub |
| 14 | +``` |
| 15 | + |
| 16 | +Then **immediately register the GPU-idle exemption** (below) or the reaper kills the job during the |
| 17 | +~30-min 550B load. |
| 18 | + |
| 19 | +## Working config (committed defaults — use as-is) |
| 20 | + |
| 21 | +`swe_teacher_cp16.yaml`: `max_total_sequence_length: 65536`, **`train_global_batch_size: 32`** |
| 22 | +(`num_prompts_per_step: 8` × `num_generations_per_prompt: 4`), `mtp_num_layers: 5` |
| 23 | +(`mtp_loss_scaling_factor: 0.3`), CP16 / EP32 / TP8 / PP1, 48 nodes (32 train + 16 gen), |
| 24 | +`SEGMENT_SIZE=8`. This config trains from scratch, CP-clean. |
| 25 | + |
| 26 | +> **Do not raise `train_global_batch_size` above 32** — GBS=128 triggers a `CONTEXT_PARALLEL_GROUP` |
| 27 | +> `all_to_all` hang (600s watchdog). 65k or 190k seq length both work at GBS ≤ 32. |
| 28 | +
|
| 29 | +## Cluster / launch facts |
| 30 | + |
| 31 | +- **Account** `nemotron_sw_post` · **partition** `batch` · **QOS** `short` (2× priority, MaxWall 2h) · **walltime** `1:59:00`. |
| 32 | +- **48 nodes** = 32 train + 16 generation (`NUM_TRAIN_NODES=32`, `NUM_GEN_NODES=16`), 4 GPU/node. |
| 33 | +- **Container:** `$Z/enroot-images/nvcr.io+nvidian+nemo-rl+nightly.2026-07-13.squashfs` |
| 34 | + where `Z=/lustre/fsw/portfolios/llmservice/users/zhiyul`. The mcore worker venv builds at runtime via |
| 35 | + `uv run --extra mcore` (~5-min transformer-engine compile). |
| 36 | +- Model / data / SIFs are all under `$Z` (see the launcher's `MODEL_PATH`, `TRAIN_PATH`, `swe_sifs`). |
| 37 | + |
| 38 | +## GPU-idle reaper exemption (REQUIRED) |
| 39 | + |
| 40 | +The 550B dist-ckpt load sits at SM≈0 for ~30 min; the auto-reaper cancels idle jobs after 30 min. Set |
| 41 | +the exemption **while PENDING or right after RUNNING**: |
| 42 | + |
| 43 | +```bash |
| 44 | +JOB=<jobid> |
| 45 | +scontrol update jobid=$JOB Comment='{"OccupiedIdleGPUsJobReaper":{"exemptIdleTimeMins":"120","reason":"benchmarking","description":"550B dist-ckpt load ~30min SM~0; SWE rollouts idle GPUs"}}' |
| 46 | +squeue -j $JOB -o %k # verify the JSON is set |
| 47 | +``` |
| 48 | + |
| 49 | +## Required settings (keep these — the recipe depends on them) |
| 50 | + |
| 51 | +| Setting | Value | |
| 52 | +|---|---| |
| 53 | +| MoE backend (vLLM) | `moe_backend: triton` | |
| 54 | +| Expert parallel | `expert_model_parallel_size: 32` | |
| 55 | +| Seq-len divisor | `make_sequence_length_divisible_by: 256` | |
| 56 | +| MTP head | `mtp_num_layers: 5`, `mtp_loss_scaling_factor: 0.3` | |
| 57 | +| Batch size | `train_global_batch_size: 32` (do not exceed) | |
| 58 | +| SWE concurrency | `swe_agents concurrency: 64` | |
| 59 | +| Topology | `cluster.segment_size: 8` + `SEGMENT_SIZE=8` (`--segment`), one EP group per NVLink rack | |
| 60 | +| NCCL transport | `ray.sub` head+worker env: `NCCL_NET=IB`, `NCCL_NVLS_ENABLE=1`, `NCCL_GIN_*`, `HYBRID_EP_CACHE_DIR` | |
| 61 | + |
| 62 | +`checkpointing.save_period=1` (launcher) writes a 550B checkpoint **every step** — drop it for anything |
| 63 | +but short runs. |
| 64 | + |
| 65 | +## Running as a different user (within HSG) |
| 66 | + |
| 67 | +Read paths (model, data, container, SIFs) are world-readable under `.../users/zhiyul` — no copy needed. |
| 68 | +Write targets are scoped per-user via `WRITE_ROOT` (default `/lustre/fsw/portfolios/llmservice/users/$USER`: |
| 69 | +HF cache, uv caches, per-agent venvs, results/checkpoints/logs). A teammate needs to: |
| 70 | +- have Slurm account `nemotron_sw_post` (or override `SLURM_ACCOUNT`); |
| 71 | +- optionally `export WRITE_ROOT=<your writable dir>`; |
| 72 | +- provide their own creds for `source .../secrets.sh` (the model is local, so `HF_TOKEN` is usually |
| 73 | + unnecessary). Do **not** rely on zhiyul's `secrets.sh`. |
| 74 | + |
| 75 | +## Monitor |
| 76 | + |
| 77 | +```bash |
| 78 | +JOB=<jobid>; LD=results/ultra-swe-teacher-cp16/ray_logs/$JOB-logs |
| 79 | +grep -aoE "training_step=[0-9]+|Watchdog caught|EngineDeadError" "$LD/ray-driver.log" | sort | uniq -c |
| 80 | +``` |
| 81 | + |
| 82 | +- Healthy: `number of parameters on` → rollout → `training_step=0` → `1` → … Step 0 can take ~1 h on a |
| 83 | + hard SWE batch (rollout-bound, not a hang — check worker-log mtimes are fresh, not the driver log). |
| 84 | +- **Success:** `training_step` advances with **zero `Watchdog caught`** and zero `EngineDeadError`. |
| 85 | +- If `Watchdog caught … CONTEXT_PARALLEL_GROUP`: batch size too large — keep GBS ≤ 32. |
| 86 | +- If `EngineDeadError` / `Hit N global ClientOSError`: generation overload — lower `concurrency` or raise the `ray.sub` ulimit. |
| 87 | + |
| 88 | +## Security |
| 89 | + |
| 90 | +`HF_TOKEN` is sourced on the login node and must be redacted from all output (`grep -v HF_TOKEN`); never |
| 91 | +bake it into logs. The model is local, so the token is typically unneeded. |
0 commit comments