Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Validate and use CPU offloading in Megatron Bridge, including layer-level activation offloading and fractional optimizer state offloading with HybridDeviceOptimizer.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 18% | 0% |
| case-20 | ✗→✓ | ▲ Improved | 44% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 159% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 52% | 0% |
| case-21 | ✗→✓ | ▲ Improved | 32% | 0% |
Two independent mechanisms to move data from GPU to CPU memory:
| Mechanism | Config namespace | What gets offloaded | PP restriction | |---|---|---|---| | Activation offloading | model.cpu_offloading* | Activations (and optionally weights) per transformer layer | PP must be 1 | | Optimizer offloading | optimizer.optimizer_cpu_offload | Adam optimizer states (momentum + variance) via HybridDeviceOptimizer | None |
| Situation | Recommendation | |---|---| | Large MoE model (30B+), needs PP > 1 | Optimizer offloading — activation offloading is blocked by PP=1 | | Small/medium model, PP=1 fits, activation memory dominates | Activation offloading | | Want tunable memory-speed tradeoff | Optimizer offloading with fractional optimizer_offload_fraction | | Throughput is top priority | Don't enable — offloading always adds overhead | | CUDA graphs are needed | Only optimizer offloading — activation offloading is incompatible | | Memory pressure is moderate | Optimizer offload at 25–50% fraction for best efficiency |
pythoncfg.optimizer.optimizer_cpu_offload = True cfg.optimizer.optimizer_offload_fraction = 1.0 cfg.optimizer.overlap_cpu_optimizer_d2h_h2d = True
CLI overrides:
bashoptimizer.optimizer_cpu_offload=True \ optimizer.optimizer_offload_fraction=0.5 \ optimizer.overlap_cpu_optimizer_d2h_h2d=True
pythoncfg.model.cpu_offloading = True cfg.model.cpu_offloading_num_layers = 16 cfg.model.cpu_offloading_activations = True cfg.model.cpu_offloading_weights = False cfg.model.pipeline_model_parallel_size = 1 cfg.model.recompute_granularity = None cfg.model.cuda_graph_impl = "none"
| Parameter | Default | Description | |-----------|---------|-------------| | optimizer_cpu_offload | False | Master switch | | optimizer_offload_fraction | 0.0 | Fraction of optimizer states on CPU (0.0–1.0) | | overlap_cpu_optimizer_d2h_h2d | False | Overlap GPU↔CPU transfers with compute | | use_torch_optimizer_for_cpu_offload | False | Use torch.optim instead of fused optimizer for CPU portion |
| Parameter | Default | Description | |-----------|---------|-------------| | cpu_offloading | False | Master switch | | cpu_offloading_num_layers | 0 | Number of transformer layers to offload (0 to num_layers-1) | | cpu_offloading_activations | True | Offload activations | | cpu_offloading_weights | False | Offload weights | | cpu_offloading_double_buffering | False | Double-buffer across layers while reloading |
pipeline_model_parallel_size must be 1recompute_granularity must be Nonefine_grained_activation_offloadingcpu_offloading_num_layers must be in [0, num_layers-1)use_distributed_optimizer = True (default in most recipes)optimizer_offload_fraction must be in [0.0, 1.0]Activation offloading is blocked for Qwen3-30B-A3B and similar large MoE models. The PP=1 constraint means each GPU holds all 48 layers; model weights + optimizer states alone (~70 GB) exceed H100 80 GB capacity.
bashuv run python scripts/training/run_recipe.py \ --recipe qwen3_30b_a3b_pretrain_config \ optimizer.optimizer_cpu_offload=True \ optimizer.optimizer_offload_fraction=0.5 \ train.train_iters=20 \ train.global_batch_size=8 \ train.micro_batch_size=1
bashuv run python -m pytest \ tests/unit_tests/models/test_gpt_full_te_layer_autocast_spec.py -k "cpu_offload" \ tests/unit_tests/peft/test_utils.py -k "cpu_offload" -q
1296:1310:3rdparty/Megatron-LM/megatron/core/transformer/transformer_config.pyif self.cpu_offloading and ( self.cpu_offloading_num_layers < 0 or self.cpu_offloading_num_layers >= self.num_layers ): raise ValueError(...) if self.cpu_offloading and self.pipeline_model_parallel_size > 1: raise ValueError( "Currently there is no support for Pipeline parallelism with CPU offloading" ) if self.cpu_offloading and self.recompute_granularity is not None: raise ValueError( "CPU offloading does not work when activation recomputation is enabled" )
1943:1944:3rdparty/Megatron-LM/megatron/core/transformer/transformer_config.pyif self.cpu_offloading: raise ValueError("CUDA graphs not supported with CPU offloading.")
1427:1430:3rdparty/Megatron-LM/megatron/core/transformer/transformer_config.pyif self.fine_grained_activation_offloading: assert ( not self.cpu_offloading ), "fine_grained_activation_offloading cannot be enabled with cpu_offloading."
480:518:3rdparty/Megatron-LM/megatron/core/optimizer/__init__.pyif config.optimizer_cpu_offload: # ... setup cpu/gpu optimizer classes ... optimizer = HybridDeviceOptimizer( param_groups, offload_fraction=config.optimizer_offload_fraction, cpu_optimizer_cls=cpu_optimizer_cls, gpu_optimizer_cls=gpu_optimizer_cls, overlap_cpu_optimizer_d2h_h2d=config.overlap_cpu_optimizer_d2h_h2d, pin_cpu_grads=config.pin_cpu_grads, pin_cpu_params=config.pin_cpu_params, )
232:234:src/megatron/bridge/models/gpt_full_te_layer_autocast_spec.pyassert not config.cpu_offloading and config.recompute_granularity is None, "Cudagraphs not supported"
621:631:src/megatron/bridge/peft/utils.pyif self.config.cpu_offloading and self.config.cpu_offloading_activations: x.activation_offloading = True x, _ = self.linear_in(x) x = self.activation(x) if self.config.cpu_offloading and self.config.cpu_offloading_activations: x.activation_offloading = True x, _ = self.linear_out(x)
| Symptom | Likely Cause | How To Confirm | Fix | |---|---|---|---| | Currently there is no support for Pipeline parallelism with CPU offloading | Activation offload + PP > 1 | Check pipeline_model_parallel_size | Set PP=1 or use optimizer offloading | | CPU offloading does not work when activation recomputation is enabled | Activation offload + recompute | Check recompute_granularity | Set recompute_granularity=null | | fine_grained_activation_offloading cannot be enabled with cpu_offloading | Both offloading modes enabled | Check both flags | Use one or the other | | CUDA graphs not supported with CPU offloading | CUDA graphs + activation offload | Check cuda_graph_impl | Set cuda_graph_impl="none" | | OOM with activation offloading | Model too large for PP=1 | Check allocated memory vs 80 GB | Use optimizer offloading with PP > 1 | | Extreme slowdown (>4x) | 100% optimizer offload, CPU Adam bottleneck | Compare iter time at different fractions | Reduce fraction or enable overlap_cpu_optimizer_d2h_h2d | | OOM at partial optimizer offload | Insufficient offload for this config | Check memory at different fractions | Increase fraction or add PP |
(30B+ MoE) that need pipeline parallelism.
~4.2x at 100% for Qwen3-30B-A3B).
the dominant bottleneck.
fine_grained_activation_offloading is a separate module-level approachthat works with PP > 1 but cannot be combined with layer-level cpu_offloading.
Other measured skills in the registry, with their headline benchmark lift.