Add offload to gradient checkpointing - #48444
Merged
Merged
Conversation
Gradient checkpointing keeps one activation per checkpointed layer on the device, which is `layers x sequence x hidden` bytes and dominates at long sequence lengths. `offload` holds those in pinned host memory instead, through torch's `save_on_cpu`, so it follows whichever checkpointing path the model already uses.
Document `offload` in `TrainingArguments.gradient_checkpointing_kwargs`, next to `every_n_layers`, and use the `backend_*` test helpers instead of `torch.accelerator` directly.
|
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. |
Contributor
CI recapDashboard: View test results in Grafana |
ArthurZucker
approved these changes
Sep 1, 2026
ArthurZucker
left a comment
Collaborator
There was a problem hiding this comment.
Perfect PR!
Maybe a todo is to auto enable this in case of 90% memory taken, or we detect long sequence length etc
Would recompile potentially, but its a great default no?
Member
Author
|
I'll have to measure this! |
qgallouedec
added a commit
to huggingface/trl
that referenced
this pull request
Sep 1, 2026
…rate one huggingface/transformers#48444 landed the same offload behind `gradient_checkpointing_kwargs={"offload": True}`, so the example no longer needs an unreleased accelerate. Measured back to back on one 8xH100 node: 379.76 s/step with transformers, 379.75 s/step with huggingface/accelerate#4175, same loss.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Gradient checkpointing still keeps one activation per checkpointed layer on the device. At long sequence lengths that is the dominant term:
layers x sequence x hiddenbytes, so Qwen3-8B at 128k tokens is 36 GB of it. This adds an option to hold those in pinned host memory instead.It is a wrap of
gradient_checkpointing_funcaround torch'ssave_on_cpu(pin_memory=True), so it follows whichever path the model already uses and needs no per-model support.It frees exactly what the arithmetic says
Memory resident after the forward, where every layer's saved input is still live. Qwen3 config, bf16, one H100:
layers x seq x hidden x 2(How much of that shows up in peak memory depends on where your peak is. On the 28-layer run above the peak only moved 11.13 -> 10.16 GB, because it sits at the end of the backward where gradients dominate and the saved inputs are already freed. The option pays off when activations dominate the peak, which is the long-sequence case it is meant for.)
Cost
Both copies run on the compute stream, so the step gets slower. There is no separate copy stream and no backward prefetch; that is pytorch/pytorch#158657, and this option does not wait for it.
Setups
Qwen3-1.7B base, 32k tokens, peak memory. The DeepSpeed row is at 8k: at 32k that engine takes a materializing attention path and asks for a 64 GiB allocation, unrelated to this option.