Skip to content

REINFORCE++ training and numerical validation report

This report accompanies the two algorithm definitions in REINFORCE++ and REINFORCE++-baseline. It records the numerical tests and a frozen, equal-budget Qwen3-0.6B comparison against GRPO. The experiment is a stability and implementation-validation study, not a claim that one algorithm is statistically superior.

Scope and evidence boundary

  • Proposal: Task 29 issue #192
  • Sanitized reproducibility evidence: logs, expanded commands, metrics and manifest
  • Experiment source commit: 5f7cd574372288391bb1c41ca0677422cd31e725
  • Experiment upstream base: b095ba68ce95c7d98762cf128eab630878f394e6
  • Post-experiment rebase base: 0bc99af8dd39de8fd99c588a98b3f3a463bc818c
  • Model: Qwen3-0.6B
  • Training data: GSM8K train_clean.parquet, 7,473 rows
  • Algorithms: GRPO, REINFORCE++, and REINFORCE++-baseline
  • Training repetitions: seeds 42, 1234, and 2026

The GPU results below remain attributed to the exact experiment commit. The branch was later rebased onto the newer upstream base and the CPU numerical and regression tests were rerun. No post-rebase GPU result is claimed.

The Git tree does not include checkpoints, data, credentials, cluster paths, or complete raw logs. The public sanitized evidence release contains the nine accepted training logs, nine accepted evaluation logs and summaries, all 18 expanded commands, GPU samples, report CSV/SVG files, and an internal SHA256 manifest. Its compressed archive SHA256 is 0b52d8e8e6a85ff534e16569dd48c9dbef336402a2c80b6aa96b8bf2ffd7834f. The private local evidence bundle additionally retains raw TensorBoard event files, evaluation JSONL files, and checkpoints; none is required to reproduce the published tables from the released CSV files.

Machine-readable, path-free evidence used by the figures and tables is published with the documentation:

Algorithm contract

The comparison intentionally changes the advantage and KL contracts, while holding the workload fixed:

AlgorithmAdvantageNormalizationKL regularization
REINFORCE++terminal reward plus token k1 KL shaping, followed by reverse return with gamma=1global population moments over all valid response tokens and DP ranksk1 inside the shaped reward; no independent KL loss
REINFORCE++-baselinereward minus the inclusive same-prompt group mean; no group-std divisionthe same global valid-token population normalizationseparate k2 KL loss
GRPOsame-prompt group centering and group-std scalingexisting per-group normalizationseparate k2 KL loss

Both new variants use a token-level PPO clipped surrogate and response-mean loss reduction. Padding and mask-zero tokens contribute to neither moments nor loss. The dedicated distributed normalizer uses population variance (ddof=0) and rsqrt(max(variance, 1e-8)). A zero-variance population returns finite zeros; a globally empty mask triggers a coordinated device-side asynchronous error without extracting a host scalar in the training hot path.

Because REINFORCE++ also changes where and how KL is injected, the comparison between REINFORCE++ and the baseline variant is an algorithm-package comparison, not a single-factor baseline ablation. The cleanest mechanism comparison is baseline versus GRPO: both use independent k2 regularization, but differ in group/global normalization.

Environment and frozen workload

ItemFrozen value
Image digestdbd4c122f11e2e83f955ceeeadf541573c46f6458c47d892ce74c03794ed317e
Python / PyTorch3.12.3 / 2.11.0+cu129
CUDA runtime12.9
Ray / SGLang2.56.0 / 0.5.12.post1
GPU1 x NVIDIA A40 48 GB per run
CPU / host memory16 CPU / 64 GiB per run
Steps50 Actor updates per run
Batch geometry4 prompts x 8 responses; global batch 32
Response cap1,024 tokens
Dynamic token cap4,096 tokens per GPU
Learning rate / PPO clip1e-6 / 0.2
RewardRelax rule-based math reward
Samplingtemperature 1.0; identical seed set and common settings

Online evaluation was disabled because repeating the full 1,319-prompt test set every ten steps would have dominated the training-generation budget. Each iteration-49 checkpoint was instead evaluated once on the same frozen 256-row subset, with four responses per prompt and evaluation seed 29. This produces 1,024 responses per checkpoint.

The first materialized subset kept the original GSM8K rationale-form labels and had SHA256 9f13d3bb27995a3902a11d879b31b909b3aed6fa3bd5b7a14928a56c313c8db4. Relax's math reward expects the scalar target used by the training file, so the questions and order were preserved while each label was deterministically converted with answer.rsplit("####", 1)[1].strip(). The accepted clean-label subset has SHA256 b4a52290777ef180e5af2602e6dfc1614dda35b4b8534109acb13abbccfb4fce. The incompatible-label run is excluded and documented below.

Reproduction entry point

The parameterized recipe supports all three compared algorithms. A portable formal invocation is:

bash
MODEL_PATH=/path/to/Qwen3-0.6B \
PROMPT_DATA=/path/to/gsm8k/main/train_clean.parquet \
OUTPUT_DIR=/path/to/output/<algorithm>-<seed> \
ADVANTAGE_ESTIMATOR=<grpo|reinforce_plus_plus|reinforce_plus_plus_baseline> \
NUM_ROLLOUT=50 \
SEED=<42|1234|2026> \
ROLLOUT_BATCH_SIZE=4 \
N_SAMPLES_PER_PROMPT=8 \
GLOBAL_BATCH_SIZE=32 \
ROLLOUT_MAX_RESPONSE_LEN=1024 \
MAX_TOKENS_PER_GPU=4096 \
REWARD_NUM_WORKERS=4 \
REWARD_MAX_CONCURRENCY=16 \
SGLANG_MEM_FRACTION_STATIC=0.40 \
USE_HEALTH_CHECK=1 \
bash examples/algorithms/run-qwen3-0.6B-1xgpu-reinforce-plus-plus.sh

The recipe supplies the variant-specific k1/k2, normalization, and validation arguments. The cluster wrapper used one isolated Ray runtime, cache, temporary directory, output directory, and port set per Slurm job. It set PYTHONNOUSERSITE=1 and bind-mounted the host checkout into the immutable container.

The site-specific Slurm expansion for every formal training was:

bash
sbatch \
  --partition=ShangHAI --account=hexm-shanghai \
  --gres=gpu:NVIDIAA40:1 --cpus-per-task=16 --mem=64G \
  --time=06:00:00 \
  --export=ALL,TASK29_ALGORITHM=<algorithm>,TASK29_SEED=<seed>,TASK29_NUM_ROLLOUT=50,TASK29_ROLLOUT_BATCH_SIZE=4,TASK29_N_SAMPLES_PER_PROMPT=8,TASK29_GLOBAL_BATCH_SIZE=32,TASK29_MAX_RESPONSE_LEN=1024,TASK29_MAX_TOKENS_PER_GPU=4096,TASK29_SGLANG_MEM_FRACTION=0.40,TASK29_REWARD_NUM_WORKERS=4,TASK29_REWARD_MAX_CONCURRENCY=16,TASK29_USE_HEALTH_CHECK=1,TASK29_USE_EVAL=0 \
  <job-isolated-wrapper.sbatch>

The wrapper verified the source commit, model/data/image inputs, runtime module paths and visible A40 before invoking the portable recipe above. It gave each job distinct Ray, Serve, cache, temporary and output roots. Site paths and the wrapper itself are not a portable project API; the complete algorithm invocation is the recipe command above. The path-free evidence index records every accepted training and evaluation job, while the SHA256-verified local bundle retains the expanded commands and raw logs for audit.

Numerical and regression validation

The independent float64 test references do not call the production return, advantage, normalization, policy-loss, KL-loss, or reduction functions. They compare shaped reward, return, raw/normalized advantage, token loss, and response-reduced loss element by element at atol=rtol=1e-6.

Coverage includes:

  • response lengths [1, 3, 5], right padding, and an internal mask hole;
  • finite, NaN, and Inf sentinels outside the mask and exact mask-zero outputs;
  • all-zero reward, nonzero KL, zero variance, and a single valid token;
  • baseline k=1 rejection;
  • upper/lower PPO clipping and positive/negative advantages;
  • independent k2 token and response-reduced losses;
  • a real two-process Gloo process group with real all_reduce operations;
  • unequal populations, one empty local rank, repartition invariance, one global token, zero variance, and a globally empty mask.

After rebasing onto upstream 0bc99af, the focused suite reported:

text
55 passed, 2 skipped in 20.37s

The two host skips require Megatron imports unavailable in the host Conda environment. The broader host regression reported:

text
204 passed, 12 skipped, 3 warnings in 18.61s

A post-rebase CPU-only Slurm run in the pinned container reported:

text
57 passed, 1 skipped, 30 warnings in 22.65s

The sole skip is the newly upstreamed FP16 test module, whose standalone container process cannot import the image's root-owned Megatron checkout. It is not a Task 29 test. A git range-diff marks all five Task 29 commits as patch-identical before and after the rebase, so the upstream FP16 change was added without altering the trained Task 29 implementation.

A final pre-review audit hardened boolean masking against non-finite padding, made a fully masked local response participate safely in global DP statistics, and added a production-dispatch integration test. The updated focused host suite reported 62 passed, 2 skipped; the broader tests/utils + tests/core regression reported 209 passed, 12 skipped, 3 warnings. The two focused skips remain upstream modules that require a full Megatron installation. These post-experiment changes affect only masked/degenerate inputs and monitoring scalar synchronization; the GPU results remain attributed to the frozen experiment commit above.

Following maintainer review, the implementation was rebased again onto upstream ce650113 and narrowed without changing either algorithm's numerical contract. Commit 0e1531b replaces the per-batch global_count.item() check with a device-side asynchronous assertion and a finite device-side denominator. It also restores relax/backends/megatron/cp_utils.py exactly to upstream and moves non-finite masked-token protection into a reducer wrapper selected only for the two REINFORCE++ estimators. GRPO, GSPO, SAPO and the other existing algorithms therefore retain the upstream shared-reducer behavior.

The review-fix validation reported:

  • 51 passed in the focused Task 29 suite, including the real two-process Gloo collective;
  • 224 passed, 12 skipped for tests/utils + tests/core in the pinned container;
  • 168 passed, 4 skipped for the complete Megatron backend suite in the pinned container;
  • a successful VitePress 1.6.4 production build for both English and Chinese pages;
  • 100 CUDA iterations under PyTorch synchronization debug mode without a host-synchronization error (TASK29_CUDA_SYNC_DEBUG_OK).

Two post-review three-step Qwen3-0.6B smoke runs exercised the narrowed production dispatch on NVIDIA A40 GPUs: REINFORCE++ job 938288 and REINFORCE++-baseline job 938293. Both jobs completed all three Actor updates, passed the structured finite-metric log validator, produced non-empty TensorBoard, checkpoint, and rollout artifacts, and left an empty job-scoped Ray cleanup list.

At the experiment commit, the pinned container passed 43 Task 29 tests and 14 metrics tests. All nine formal trainings produced 50 rollout records, 50 Actor updates, finite TensorBoard metrics, and an iteration-49 checkpoint. All nine accepted evaluations produced 1,024 responses, a non-empty summary and TensorBoard file, the TASK29_EVAL_OK gate, and an empty job-scoped Ray cleanup list.

Training stability

Across-seed dispersion in this report is the sample standard deviation (ddof=1, n=3). The stable-training table first averages each run across steps 40--49, then computes the mean and sample standard deviation across the three run-level values.

AlgorithmLast-10 raw rewardLast-10 PG lossLast-10 independent KL lossLast-10 grad norm
GRPO0.5417 ± 0.0273-0.000000 ± 0.0000000.006024 ± 0.0003801.1674 ± 0.0396
REINFORCE++0.5469 ± 0.0188-0.111379 ± 0.015769N/A (k1 reward shaping)1.7015 ± 0.0244
REINFORCE++-baseline0.5344 ± 0.0143-0.021490 ± 0.0104830.006048 ± 0.0020021.5847 ± 0.0499

train/ppo_kl is the response-reduced old-policy/current-policy log-prob difference used by the PPO importance ratio. It is zero in all 450 published rows for this frozen workload with one Actor update per rollout batch, but that is not a reference-policy KL measurement and does not imply that reference regularization was disabled. REINFORCE++ instead folds its k1 reference term into the return, while GRPO and REINFORCE++-baseline report an independent k2 term as train/kl_loss.

For a direct k1 activation check, the following table subtracts each same-step TensorBoard rollout/raw_reward scalar from rollout/returns, then averages those differences within the indicated interval. All three REINFORCE++ commands used --kl-coef 0.01 --kl-loss-type k1. The consistently negative, nonzero differences after policy movement show that reference KL shaping reached the production return rather than remaining a recipe-only setting.

Seed / jobAll-50 mean differenceLast-10 mean differenceFinal-step difference
42 / 937653-0.007241-0.017225-0.019743
1234 / 937680-0.007396-0.018403-0.020091
2026 / 937689-0.006929-0.017273-0.014912

The baseline's separately optimized k2 loss is independently visible in the stability table (0.006048 ± 0.002002 over steps 40--49). The released expanded commands and raw logs allow both checks to be recomputed without access to the cluster.

Training reward curves

train/loss, rollout/rewards, and processed advantage magnitudes do not have a common cross-algorithm meaning. In particular, REINFORCE++ has no independent KL-loss term, whereas the GRPO and baseline total losses include one. The next two figures are therefore optimization diagnostics rather than algorithm-ranking metrics.

Training total-loss curves

Independent k2 KL-loss curves

The normalized-advantage standard deviation was exactly 1 at all 150 REINFORCE++ steps. The baseline variant produced finite zero advantages on 7 of 150 steps where the global raw advantage population had zero variance; its other steps had standard deviation 1. This is the intended degenerate-input behavior, not a NaN or silent sample loss.

Normalized advantage standard deviation

Length, truncation, and efficiency

The all-50-step summaries are:

AlgorithmRaw rewardMean response lengthTruncationResponse tok/sPeak GPU memory
GRPO0.5304 ± 0.0112896.7 ± 6.10.5358 ± 0.0148409.8 ± 0.735.33 ± 0.33 GiB
REINFORCE++0.5144 ± 0.0087905.9 ± 0.30.5608 ± 0.0150405.3 ± 1.135.22 ± 0.09 GiB
REINFORCE++-baseline0.5346 ± 0.0113896.9 ± 17.20.5396 ± 0.0328409.2 ± 0.835.26 ± 0.09 GiB

Mean Slurm elapsed time was 65.6 minutes for GRPO, 66.9 minutes for REINFORCE++, and 65.7 minutes for the baseline variant. Throughput, elapsed time, and peak memory are close; this experiment does not indicate a material systems-cost difference among the algorithms.

Mean response-length curves

Truncation curves

Response-token throughput curves

The response cap is an important limitation: roughly 54--56% of training responses and 40--44% of evaluation responses were truncated. Length behavior may affect the observed quality ordering and must not be hidden by reporting accuracy alone.

Fixed-subset final-checkpoint evaluation

Each row below is an independently trained checkpoint evaluated with the identical prompt order, scalar labels, sample count, decoding parameters, and evaluation seed.

AlgorithmSeedReward / pass@1pass@2pass@4TruncationMean length
GRPO420.60060.70960.77730.3926844.1
GRPO12340.59960.69730.76170.4355854.5
GRPO20260.62300.71880.79300.3711834.1
REINFORCE++420.60160.71350.77340.4385867.3
REINFORCE++12340.57520.69600.78120.4443859.6
REINFORCE++20260.58300.69270.76560.4316855.0
REINFORCE++-baseline420.58590.69080.77730.4639866.6
REINFORCE++-baseline12340.59860.69270.76950.4395867.2
REINFORCE++-baseline20260.62790.73960.82030.3594824.2

Aggregate results:

AlgorithmReward / pass@1pass@2pass@4Truncation
GRPO0.6077 ± 0.01330.7086 ± 0.01080.7773 ± 0.01560.3997 ± 0.0328
REINFORCE++0.5866 ± 0.01350.7007 ± 0.01120.7734 ± 0.00780.4382 ± 0.0064
REINFORCE++-baseline0.6042 ± 0.02150.7077 ± 0.02760.7891 ± 0.02730.4209 ± 0.0547

Final-checkpoint evaluation reward

The paired reward differences by training seed are:

ComparisonSeed 42Seed 1234Seed 2026Mean ± sample SDExploratory 95% t-CI
REINFORCE++ - GRPO+0.0010-0.0244-0.0400-0.0212 ± 0.0207[-0.0726, 0.0303]
baseline - GRPO-0.0146-0.0010+0.0049-0.0036 ± 0.0100[-0.0285, 0.0213]
REINFORCE++ - baseline+0.0156-0.0234-0.0449-0.0176 ± 0.0307[-0.0938, 0.0587]

These intervals use only three paired training seeds (df=2) and all cross zero. GRPO has the highest mean reward, while the baseline variant has the highest mean pass@4, but rankings reverse across seeds. The evidence supports stable execution and an initial fixed-subset comparison, not a superiority or statistical-significance claim.

Incidents and resolutions

IncidentEvidence boundaryResolution
Container preflight lacked RuffCUDA/import checks passed; pytest had not runkept Ruff as a host/static gate and reran container pytest successfully
Runtime-env JSON gained an extra braceRay started; training never entered parameter parsingreplaced Bash default expansion with an explicit empty-value branch and added regression coverage
8/12 CPU smoke allocations could not schedule Rollout or RewardWorker actorsno optimizer step; excludedformalized 16 CPU per run and bounded reward-worker concurrency
Training job 937654 exited 2:0 after all 50 updatescomplete TensorBoard, rollout files, checkpoint, success marker, and empty cleanup are retainedreplaced an unrestricted loss...nan regex that matched generated text containing Nancy with a structured log validator; Slurm state remains reported as failed
Eval-only startup used an invalid zero-step schedule and then a wrong config pathno accepted generation; excludedretained a valid parser schedule without calling the training loop and corrected the container path
Eval job 937775 used rationale-form GSM8K labels and produced all-zero rewardvalidates weight sync, generation, metrics routing, and cleanup only; quality metrics excludeddeterministically normalized labels to scalar targets and reran all nine accepted evaluations

No failed smoke, preflight, or incompatible-label result is mixed into the formal comparison.

Limitations and conclusion

  1. Three training seeds are sufficient for a repeatability check, not a strong significance claim.
  2. Evaluation covers one frozen 256-prompt subset and one decoding seed; it is not a full GSM8K benchmark.
  3. There is no identically evaluated initial-model checkpoint, so this report cannot claim improvement over the base model.
  4. Formal rollout generation was seeded but not fully deterministic; equal seeds fix common inputs and random-source configuration, not token-for-token identity across different policies.
  5. The high response truncation rate may affect the quality ordering.

Within those limits, both new estimator names satisfy their documented mathematical contracts, align element by element with independent references, pass real cross-rank Gloo tests, and complete the same nine-run training and evaluation budget as GRPO without NaN, Inf, OOM, or unexplained sample loss. The baseline variant tracks GRPO closely in mean reward and has the highest mean pass@4 in this small study; standard REINFORCE++ has longer responses and more truncation. A larger follow-up should prioritize a longer response cap, more training seeds, the full evaluation set, and an initial-checkpoint control.

Released under the Apache 2.0 License.