Size review of NVIDIA-NeMo/RL #4507, stacked on #4506.
Line counts are from git diff 834241af deb0e146. All permalinks pin the PR head deb0e146. Review comments are in a pending review; the links work once it is published.
Three pages on this PR โ this one (round 1, an older head): which lines do the checking, and which repeat code that already exists.
The test runs the same small Workplace workload twice and requires every trained row to match token for token. The checks that can fail the run are a short list: rows match, each restored prefix trained exactly once with the right length, no old prefix keys left behind, rewards are not all the same, and generation log-probs agree. Most of the remaining code prints reports, re-checks something already checked, or rebuilds a training-data dump that NeMo-RL already writes.
| What the PR writes | Why it can go | lines | |
|---|---|---|---|
| A | A wrapper around the trainer that saves every trained row to JSONL (turn_recovery_hook.py:57, parity.py:65-141) | NeMo-RL already writes this file with async_rl.log_full_train_data. A ~20-line probe for staging keys stays. Diff below. | ~125 + 28 test |
| B | Row order, per-rollout timelines, Kendall tau (parity.py:691-884) | Reports only. Its one check, group order inside a step, cannot change what trains: each step trains as one chunk of 4 groups. | ~215 + 127 test |
| C | Hand-written Spearman, Pearson, percentiles (parity.py:548-661) | The check reads 3 numbers. With โฅ99% of log-probs identical, Spearman is ~1 whatever happens. Two numbers in ~15 lines of torch do the job. | ~125 + 70 test |
| D | A 5-way sorting of token differences that excuses some rows (parity.py:455-523) | It also lets real restore bugs pass โ see the other page. Every other row already has to match exactly. | ~70 + 115 test |
| E | Smaller items: a check that can never fail (:346), two checks that repeat others (:285, :367), a fallback for a file format that cannot appear (:304), copied readers and log parsers, report printing review comment โ parity.py:350review comment โ parity.py:367review comment โ parity.py:285review comment โ parity.py:306review comment โ parity.py:54 | Each repeats a check or a helper that already exists in the same stack. | ~165 |
Nothing below is implemented, and it has not been run.
Where the fix lands: RL test files only.
prefix_recovery.sh, the hook, and the parity script.
No product change: the dump already exists. It is written at the advantage stage with token ids, loss mask, advantages, generation log-probs, rewards and sample mask, and a retried step replaces its own file (train_data_dump.py:95).
The author's earlier version of this harness (#4320) read these same files.
@@ grpo_async_gym_single_controller_prefix_recovery.sh L162 ยท COMMON_OVERRIDES COMMON_OVERRIDES=( policy.model_name="$MODEL_NAME" + # Built-in per-step dump of every trained row: what the parity check compares. + ++async_rl.log_full_train_data=true @@ _single_controller_turn_recovery_hook.py L57-L139 ยท _TrainingPayloadRecorder -class _TrainingPayloadRecorder: - """Test-only TQPolicy wrapper that records the rows sent to training.""" โฆ 81 lines: read rows back from the data plane, serialize, append โฆ +class _StagingKeyProbe: + """Record the live staging keys per train step; the dump has everything else.""" โฆ ~20 lines: wrap begin_train_step, append list_sample_ids(staging) โฆ @@ _gym_prefix_recovery_parity.py L65-L141 ยท serialize / append / _tensor / _generation_identity -def serialize_training_batch( โฆ 76 more deleted lines โฆ +def _load_dump(log_dir: Path) -> list[dict[str, Any]]: + # One file per optimizer step, written only after the step finished. + return [row for path in sorted(log_dir.rglob("train_data_step*.jsonl")) + for row in _read_jsonl(path)]
Each run (reference, phase 1, phase 2) gets its own log folder, so phase 1's files never mix with phase 2's. Today phase 1 and phase 2 share one (:234, :285).
review comment โ turn_recovery_hook.py:57
top_p=0.000001 means rewards never reach the weights, so steps 2 and 3 cost GPU time without testing learning. That is a separate review comment, not on this page.