option
MaisonMaison Skill Science des données et ML nemo-mbridge-perf-cpu-offloading

nemo-mbridge-perf-cpu-offloading

NVIDIA/skills NVIDIA/skills

Configurer et valider le délestage CPU pour l'entraînement de Megatron Bridge, y compris le délestage des activations et celui de l'état de l'optimiseur à l'aide de HybridDeviceOptimizer.

...Développer tout
2
Heure mise à jour 28 septembre 2026

Déchargement du processeur

Références

  • Documentation stable : @docs/training/cpu-offloading.md
  • Métadonnées structurées : @skills/nemo-mbridge-perf-cpu-offloading/card.yaml

De quoi s'agit-il ?

Deux mécanismes indépendants permettant de transférer des données de la mémoire du GPU vers celle du CPU :

Mécanisme Espace de noms de configuration Ce qui est déchargé Restriction PP
Déchargement d’activation model.cpu_offloading* Activations (et, éventuellement, poids) par couche de transformateur PP doit être égal à 1
Déchargement de l’optimiseur optimizer.optimizer_cpu_offload États de l'optimiseur Adam (momentum + variance) via HybridDeviceOptimizer Aucun

Décision rapide

Situation Recommandation
Modèle MoE volumineux (plus de 30 milliards), nécessite un PP > 1 Déchargement de l’optimiseur — le déchargement de l’activation est bloqué par PP=1
Modèle petit/moyen, PP = 1 convient, la mémoire d’activation domine Délestage des activations
On souhaite un compromis réglable entre mémoire et vitesse Déchargement de l’optimiseur avec un paramètre fractionnaire optimizer_offload_fraction
Le débit est la priorité absolue Ne pas activer — le déchargement ajoute toujours une surcharge
Des graphes CUDA sont nécessaires Déchargement de l’optimiseur uniquement — le déchargement d’activation est incompatible
La pression sur la mémoire est modérée Déchargement de l’optimiseur à un taux de 25 à 50 % pour une efficacité optimale

Activation

Déchargement de l’optimiseur vers le CPU (recommandé pour les grands modèles)

cfg.optimizer.optimizer_cpu_offload = True
cfg.optimizer.optimizer_offload_fraction = 1.0
cfg.optimizer.overlap_cpu_optimizer_d2h_h2d = True

Remplacements via l'interface en ligne de commande :

optimizer.optimizer_cpu_offload=True \
optimizer.optimizer_offload_fraction=0,5 \
optimizer.overlap_cpu_optimizer_d2h_h2d=True

Déchargement des activations vers le CPU (modèles petits/moyens uniquement)

cfg.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"

Référence des paramètres de configuration

Déchargement de l’optimiseur

Paramètre Valeur par défaut Description
optimizer_cpu_offload Faux Commutateur principal
optimizer_offload_fraction 0,0 Fraction des états de l'optimiseur sur le CPU (0,0–1,0)
overlap_cpu_optimizer_d2h_h2d Faux Superposition des transferts GPU↔CPU avec le calcul
use_torch_optimizer_for_cpu_offload Faux Utiliser torch.optim à la place de l'optimiseur fusionné pour la partie CPU

Déchargement des activations

Paramètre Valeur par défaut Description
cpu_offloading Faux Commutateur principal
cpu_offloading_num_layers 0 Nombre de couches du transformateur à décharger (de 0 à num_layers-1)
cpu_offloading_activations Vrai Décharger les activations
cpu_offloading_weights Faux Poids de déchargement
cpu_offloading_double_buffering Faux Double tampon entre les couches lors du rechargement

Compatibilité et contraintes

Déchargement des activations

  • pipeline_model_parallel_size doit être égal à 1
  • recompute_granularity doit être None
  • Ne peut pas être combiné avec fine_grained_activation_offloading
  • Ne peut pas être combiné avec les graphes CUDA
  • cpu_offloading_num_layers doit être compris entre 0 et num_layers-1

Délestage de l’optimiseur

  • Nécessite use_distributed_optimizer = True (valeur par défaut dans la plupart des recettes)
  • Aucune restriction concernant le PP, le recalcul ou les graphes CUDA
  • optimizer_offload_fraction doit être compris entre 0,0 et 1,0

Cas pratique : grands modèles MoE

Le déchargement des activations est bloqué pour Qwen3-30B-A3B et les grands modèles MoE similaires. La contrainte PP=1 implique que chaque GPU contient les 48 couches ; les poids du modèle et les états de l’optimiseur à eux seuls (~70 Go) dépassent la capacité de 80 Go du H100.

Commande minimale d'exécution

uv 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

Vérification

Tests unitaires

uv 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

Critères de réussite

  • La validation de la configuration réussit pour le mode de déchargement sélectionné
  • L'entraînement s'achève sans erreur OOM ni NCCL
  • La perte correspond à celle de la référence sans déchargement (écart maximal < 0,001)
  • L'utilisation de la mémoire diminue proportionnellement à la fraction de déchargement

Ancrages de code

Contraintes de déchargement de l’activation MCore

       if self.cpu_offloading and (
            self.cpu_offloading_num_layers < 0 or self.cpu_offloading_num_layers >=self.num_layers
        ):
            raise ValueError(...)

        si self.cpu_offloading et self.pipeline_model_parallel_size > 1 :
            lève une exception ValueError(
                « Le parallélisme de pipeline n’est actuellement pas pris en charge avec le déchargement CPU »
            )

        if self.cpu_offloading and self.recompute_granularity is not None:
            raise ValueError(
                "Le déchargement CPU ne fonctionne pas lorsque le recalcul des activations est activé"
            )

Incompatibilité du graphe CUDA de MCore

           si self.cpu_offloading :
                lève ValueError("Graphes CUDA non pris en charge avec le déchargement CPU.")

Exclusion mutuelle entre le déchargement fin de MCore et le déchargement du CPU

       if self.fine_grained_activation_offloading:
            assert (
                not self.cpu_offloading
            ), « fine_grained_activation_offloading ne peut pas être activé avec cpu_offloading. »

Instanciation de HybridDeviceOptimizer par MCore

       if config.optimizer_cpu_offload:
            # ... configuration des classes d'optimisation CPU/GPU ...
            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,
            )

Protection du graphe CUDA de Bridge

       assert not config.cpu_offloading and config.recompute_granularity is None, « Cudagraphs non pris en charge »

Pont d'externalisation des activations dans PEFT

       si self.config.cpu_offloading et self.config.cpu_offloading_activations :
            x.activation_offloading = True
        x, _ = self.linear_in(x)
        x = self.activation(x)
        si self.config.cpu_offloading et self.config.cpu_offloading_activations :
            x.activation_offloading = True
        x, _ = self.linear_out(x)

Diagnostic des défaillances

Symptôme Cause probable Comment vérifier Solution
Le parallélisme des pipelines avec déchargement du processeur n'est actuellement pas pris en charge Déchargement d'activation + PP > 1 Vérifiez la valeur de pipeline_model_parallel_size Définissez PP=1 ou utilisez le déchargement de l'optimiseur
Le déchargement CPU ne fonctionne pas lorsque le recalcul d’activation est activé Déchargement des activations + recalcul Vérifier la valeur de « recompute_granularity » Définissez ` recompute_granularity` sur `null`
Le déchargement d'activation à granularité fine ne peut pas être activé avec le déchargement CPU Les deux modes de déchargement sont activés Vérifier les deux indicateurs Utilisez l’un ou l’autre
Les graphes CUDA ne sont pas pris en charge avec le déchargement vers le processeur Graphiques CUDA + déchargement d'activation Vérifier cuda_graph_impl Définissez cuda_graph_impl="none"
Erreur OOM avec déchargement des activations Modèle trop volumineux pour PP=1 Vérifier la mémoire allouée par rapport à 80 Go Utiliser le déchargement de l'optimiseur avec PP > 1
Ralentissement extrême (>4x) Déchargement de l’optimiseur à 100 %, goulot d’étranglement CPU Adam Comparer le temps d’itération pour différentes fractions Réduire la fraction ou activer overlap_cpu_optimizer_d2h_h2d
Erreur OOM lors d’un déchargement partiel de l’optimiseur Déchargement insuffisant pour cette configuration Vérifier la mémoire pour différentes fractions Augmentez la fraction ou ajoutez du PP

Limitations connues

  • Le délestage de l’activation nécessite PP=1, ce qui le rend impraticable pour les grands modèles (plus de 30 milliards de MoE) nécessitant un parallélisme en pipeline.
  • La perte de débit liée au déchargement de l’optimiseur est linéaire (~1,9x à 25 %, ~4,2x à 100 % pour Qwen3-30B-A3B).
  • Le chevauchement D2H/H2D n'apporte qu'un gain de vitesse d'environ 7 %, car le calcul Adam sur le CPU constitue le goulot d'étranglement principal.
  • Le « fine_grained_activation_offloading » est une approche distincte au niveau des modules qui fonctionne avec un PP > 1, mais ne peut pas être combinée avecle « cpu_offloading » au niveau des couches .
Voir sur GitHub
---
name: nemo-mbridge-perf-cpu-offloading
description: Configure and validate CPU offloading for Megatron Bridge training, including activation offloading and optimizer state offloading with HybridDeviceOptimizer.
license: Apache-2.0
---

# CPU Offloading

## References

- Stable docs: @docs/training/cpu-offloading.md
- Structured metadata: @skills/nemo-mbridge-perf-cpu-offloading/card.yaml

## What It Is

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 |

## Quick Decision

| 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 |

## Enablement

### Optimizer CPU offloading (recommended for large models)

```python
cfg.optimizer.optimizer_cpu_offload = True
cfg.optimizer.optimizer_offload_fraction = 1.0
cfg.optimizer.overlap_cpu_optimizer_d2h_h2d = True
```

CLI overrides:

```bash
optimizer.optimizer_cpu_offload=True \
optimizer.optimizer_offload_fraction=0.5 \
optimizer.overlap_cpu_optimizer_d2h_h2d=True
```

### Activation CPU offloading (small/medium models only)

```python
cfg.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"
```

## Config Parameter Reference

### Optimizer offloading

| 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 |

### Activation offloading

| 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 |

## Compatibility And Constraints

### Activation offloading

- `pipeline_model_parallel_size` must be 1
- `recompute_granularity` must be `None`
- Cannot combine with `fine_grained_activation_offloading`
- Cannot combine with CUDA graphs
- `cpu_offloading_num_layers` must be in `[0, num_layers-1)`

### Optimizer offloading

- Requires `use_distributed_optimizer = True` (default in most recipes)
- No PP, recompute, or CUDA graph restrictions
- `optimizer_offload_fraction` must be in `[0.0, 1.0]`

### Practical: large MoE models

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.

## Minimal Runnable Command

```bash
uv 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
```

## Verification

### Unit tests

```bash
uv 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
```

### Success criteria

- Config validation passes for the selected offloading mode
- Training completes without OOM or NCCL errors
- Loss matches the non-offloaded baseline (max delta < 0.001)
- Memory usage drops proportionally to offload fraction

## Code Anchors

### MCore activation offload constraints

```1296:1310:3rdparty/Megatron-LM/megatron/core/transformer/transformer_config.py
        if 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"
            )
```

### MCore CUDA graph incompatibility

```1943:1944:3rdparty/Megatron-LM/megatron/core/transformer/transformer_config.py
            if self.cpu_offloading:
                raise ValueError("CUDA graphs not supported with CPU offloading.")
```

### MCore fine-grained offloading mutual exclusion

```1427:1430:3rdparty/Megatron-LM/megatron/core/transformer/transformer_config.py
        if self.fine_grained_activation_offloading:
            assert (
                not self.cpu_offloading
            ), "fine_grained_activation_offloading cannot be enabled with cpu_offloading."
```

### MCore HybridDeviceOptimizer instantiation

```480:518:3rdparty/Megatron-LM/megatron/core/optimizer/__init__.py
        if 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,
            )
```

### Bridge CUDA graph guard

```232:234:src/megatron/bridge/models/gpt_full_te_layer_autocast_spec.py
        assert not config.cpu_offloading and config.recompute_granularity is None, "Cudagraphs not supported"
```

### Bridge activation offloading in PEFT

```621:631:src/megatron/bridge/peft/utils.py
        if 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)
```

## Failure Diagnosis

| 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 |

## Known Limitations

- Activation offloading requires PP=1, making it impractical for large models
  (30B+ MoE) that need pipeline parallelism.
- Optimizer offloading throughput penalty scales linearly (~1.9x at 25%,
  ~4.2x at 100% for Qwen3-30B-A3B).
- D2H/H2D overlap provides only ~7% speedup because CPU Adam compute is
  the dominant bottleneck.
- `fine_grained_activation_offloading` is a separate module-level approach
  that works with PP > 1 but cannot be combined with layer-level
  `cpu_offloading`.

Tous les fichiers

6 fichiers
SKILL.md 9.1k
Voir

Installer nemo-mbridge-perf-cpu-offloading

Téléchargez et décompressez les fichiers de compétences dans votre répertoire .claude/skills/.

Télécharger le ZIP

Clonez le dépôt et copiez les fichiers de compétence dans votre projet.

git clone https://github.com/NVIDIA/skills/tree/main/skills/nemo-mbridge-perf-cpu-offloading # Copy SKILL.md to your .claude/skills/ directory

Copier Copier
Configuration rapide: Copiez le dossier de la compétence dans .claude/skills/ Claude détectera automatiquement la compétence et l'utilisera
Dépôt NVIDIA/skills

Compétences similaires

web-search
Heure mise à jour 29 juin 2026
webapp-testing
Heure mise à jour 29 juin 2026
lark-base
Heure mise à jour 5 juillet 2026
agentmail
Heure mise à jour 29 juin 2026
OR