TRL: document 1M-token training and add a context-parallelism example - #6845
TRL: document 1M-token training and add a context-parallelism example#6845qgallouedec wants to merge 5 commits into
Conversation
|
The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update. |
|
Reopening from a branch actually based on #6820 — this one was cut from main, so the diff showed 125 unrelated files. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 851fd9a0a6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| #### Training at 1M tokens and beyond | ||
|
|
||
| With the setup above plus a few levers, SFT scales to million-token sequences on a single 8×H100 node. Verified configurations (bf16, `per_device_train_batch_size=1`, `loss_type="chunked_nll"` — the default): |
There was a problem hiding this comment.
Set packing false in the referenced million-token setup
The referenced setup explicitly sets packing=True, while the constraints below explain that context parallelism drops the block-diagonal mask. SFTTrainer currently only warns about packing with non-Flash attention; it does not raise based on context parallelism as claimed later. Following “the setup above” can therefore allow packed documents to attend to one another and silently corrupt the training results, so the million-token recipe must explicitly disable packing rather than relying on a nonexistent guard.
Useful? React with 👍 / 👎.
|
|
||
| The levers, roughly in the order you will need them as model size or sequence length grows: | ||
|
|
||
| 1. **Keep the default `loss_type="chunked_nll"`.** At 1M tokens, materializing `[seq, vocab]` logits costs tens of GB per GPU; the chunked loss never does. |
There was a problem hiding this comment.
Disable Liger before relying on chunked NLL
Under the setup referenced here, use_liger_kernel=True; SFTConfig.__post_init__ consequently changes the default loss to "nll", and explicitly selecting "chunked_nll" raises an incompatibility error in SFTTrainer. Thus users either hit an exception or materialize the full million-token logits tensor that this recommendation is intended to avoid, likely causing OOM. The recipe needs to set use_liger_kernel=False before calling chunked NLL the default.
Useful? React with 👍 / 👎.
| with sdpa_kernel([SDPBackend.CUDNN_ATTENTION]): | ||
| return super().training_step(*args, **kwargs) | ||
| ``` | ||
| 3. **Offload checkpointed activations to host memory** (≥ ~1.5M tokens, or ≥ ~8B parameters): set `fsdp_activation_checkpointing_offload: true` in the accelerate FSDP config. Each checkpointed layer's input — the dominant surviving activation, `layers × seq/cp × hidden` bytes — moves to pinned host memory during the forward and returns on demand during the backward. |
There was a problem hiding this comment.
Gate activation offload on a supporting Accelerate version
This option is not available in the documented minimum Accelerate 1.11.0 setup; support depends on the newer FSDP2 activation-offload change. A user satisfying the stated requirements can therefore have this configuration key rejected instead of obtaining the memory savings required for the listed 8B+ runs. Specify the first released Accelerate version that provides the option and raise the section's minimum accordingly.
Useful? React with 👍 / 👎.
| ```python | ||
| model_init_kwargs={ | ||
| "rope_parameters": {"rope_type": "yarn", "rope_theta": 1000000, "factor": 32, "original_max_position_embeddings": 32768}, | ||
| } |
There was a problem hiding this comment.
Provide the Transformers 4.x RoPE override
TRL still supports Transformers 4.x (transformers>=4.56.2), where Qwen3 expects rope_scaling plus the top-level rope_theta, not the v5-only rope_parameters dictionary shown here. On that supported dependency range this override does not configure YaRN as intended, so users can start a costly million-token run with the unscaled positional encoding and the high-loss behavior described immediately above. Include the 4.x form or explicitly require Transformers v5 for this recipe.
Useful? React with 👍 / 👎.
| - **Full-attention models only.** Models with sliding-window or chunked attention layers cannot be used: their | ||
| per-layer mask has to be dropped, which would silently turn those layers into full causal attention. | ||
| Accelerate rejects such models. This rules out much of the current crop — gpt-oss (every other layer), |
There was a problem hiding this comment.
Require the Accelerate version that rejects local attention
The stated Accelerate 1.11.0 minimum does not provide the advertised rejection of sliding-window or chunked-attention models, and TRL performs no equivalent SFT validation. With such a supported installation, selecting one of the listed models can proceed after context parallelism drops its per-layer mask, silently training full causal attention instead of the model's intended architecture. Tie this guarantee to the Accelerate release containing the validation, or warn that older versions do not enforce it.
Useful? React with 👍 / 👎.
Two things, both about training on sequences far longer than the usual few thousand tokens:
docs/source/distributing_training.md, with the configurations I verified and the levers in the order you hit them;examples/sft_long_context/, a runnable example that trains a book-length sequence per step on one 8xH100 node, plusexamples/accelerate_configs/context_parallel_8gpu.yaml.Measured
One 8xH100 node, bf16,
per_device_train_batch_size=1,loss_type="chunked_nll"(the default):Context length scales with node count (Qwen3-8B: 1M on 1 node at 364 s, 2M on 2 nodes at 696 s, 4M on
4 nodes at 1346 s), because each GPU keeps the same shard of the sequence.
It is real training, not just "it fits": Qwen3-30B-A3B with YaRN x32 on PG-19 books at 1M context goes
from loss 4.88 to 2.37 in six steps.
Assumptions
Everything here is written as if the rest of the series has landed. Each of these is a separate PR, and the text or the example changes if one of them does not merge:
activation_checkpointing_offloadcontext_parallel_8gpu.yamlsetsfsdp_activation_checkpointing_offload: true; the guide lists it as lever 3SFTTrainersubclass wrappingtraining_stepinsdpa_kernel([SDPBackend.CUDNN_ATTENTION]), and every step time above is ~1.7x largercp-eval-loss-scaling— apply CP to the evaluation patheval_lossmultiplied bycp_sizeTwo more that are not assumptions, just constraints of what exists today, both stated in the example:
and later cannot be used. Qwen3.5+ is the interesting one: three quarters of its layers are linear
attention, which is a different problem from the sliding-window case and is not covered by [New Trainer] TreeRPO: Hierarchical Credit Assignment for Deterministic-Correctness Tasks #4177's
fix, only by its refusal.
Note
Low Risk
Documentation-only change; no runtime, training, or security code is modified.
Overview
Adds a Training at 1M tokens and beyond section to the Ring Attention docs, with verified step times and peak memory for Qwen3 models from 0.6B to 32B (and a 30B MoE) on 8×H100, plus multi-node scaling for Qwen3-8B at 1M/2M/4M.
Documents the memory/speed levers in the order they become necessary: chunked NLL, cuDNN SDPA, FSDP activation offload, alltoall ring rotation + bf16 merge, param CPU offload, MLP sequence tiling, and YaRN RoPE scaling. Also states CP constraints: full causal attention only (no sliding-window models) and no packing.
Reviewed by Cursor Bugbot for commit 851fd9a. Bugbot is set up for automated code reviews on this repo. Configure here.