Accelerate documentation

DeepSpeed

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v1.15.0).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

DeepSpeed

DeepSpeed implémente tout ce qui est décrit dans l'article ZeRO. Parmi les optimisations notables, on trouve :

  1. Partitionnement de l'état de l'optimiseur (étape 1 de ZeRO)
  2. Partitionnement des gradients (ZeRO stage 2)
  3. Partitionnement des paramètres (ZeRO stage 3)
  4. Gestion personnalisée de l'entraînement en précision mixte
  5. Une gamme d'optimiseurs rapides basés sur des extensions CUDA
  6. ZeRO-Offload vers le CPU et le disque/NVMe
  7. Partitionnement hiérarchique des paramètres du modèle (ZeRO++)

ZeRO-Offload a son propre article dédié : ZeRO-Offload: Democratizing Billion-Scale Model Training. Et la prise en charge de NVMe est décrite dans l’article ZeRO-Infinity: Breaking the GPU Memory Wall for Extreme Scale Deep Learning.

DeepSpeed ZeRO-2 est principalement utilisé uniquement pour l’entraînement, car ses fonctionnalités ne sont pas utiles pour l’inférence.

DeepSpeed ZeRO-3 peut également être utilisé pour l’inférence, car il permet de charger de très grands modèles sur plusieurs GPU, ce qui serait impossible sur un seul GPU.

Accelerate intègre DeepSpeed via 2 options :

  1. Intégration des fonctionnalités de DeepSpeed via la spécification d'un deepspeed config file dans accelerate config. Il vous suffit de fournir votre fichier de configuration personnalisé ou d'utiliser notre modèle. La majeure partie de ce document est consacrée à cette fonctionnalité. Elle prend en charge toutes les fonctionnalités principales de DeepSpeed et offre à l'utilisateur une grande flexibilité. L'utilisateur peut devoir modifier quelques lignes de code en fonction de la configuration.
  2. Intégration via deepspeed_plugin. Cela prend en charge un sous-ensemble des fonctionnalités de DeepSpeed et utilise les options par défaut pour le reste des configurations. L'utilisateur n'a besoin de modifier aucun code, ce qui convient à ceux qui sont à l'aise avec la plupart des paramètres par défaut de DeepSpeed.

Que comprend l'intégration ?

Entraînement :

  1. Accelerate intègre toutes les fonctionnalités de DeepSpeed ZeRO. Cela inclut tous les stades ZeRO 1, 2 et 3, ainsi que ZeRO-Offload, ZeRO-Infinity (qui peut décharger sur disque/NVMe) et ZeRO++. Voici une brève description du parallélisme de données utilisant ZeRO - Zero Redundancy Optimizer, accompagnée d'un diagramme issu de ce article de blog ZeRO Data Parallelism

(Source : lien)

a. Étape 1 : Répartit les états de l'optimiseur entre les travailleurs/GPU parallèles de données

b. Étape 2 : Répartit les états de l'optimiseur et les gradients entre les travailleurs/GPU parallèles de données

c. Étape 3 : Répartit les états de l'optimiseur + les gradients + les paramètres du modèle entre les travailleurs/GPU parallèles de données

d. Optimizer Offload : déplace les gradients et les états de l'optimiseur vers le CPU/le disque, en s'appuyant sur le niveau 2 de ZERO

e. Param Offload : Déplace les paramètres du modèle vers le CPU/le disque, en s'appuyant sur le stade 3 de ZERO

f. Partitionnement hiérarchique : Permet une formation multi-nœuds efficace avec une formation parallèle par données entre les nœuds et un fractionnement ZeRO-3 au sein d'un nœud, construit sur la base de ZeRO Stage 3.

Note: With respect to Disk Offload, the disk should be an NVME for decent speed but it technically works on any Disk

Inférence :

  1. DeepSpeed ZeRO Inference prend en charge le ZeRO stage 3 avec ZeRO-Infinity. Il utilise le même protocole ZeRO que l’entraînement, mais n’utilise ni optimiseur ni lr scheduler, et seul le stage 3 est pertinent. Pour plus de détails, voir : ZeRO Inference.

Comment ça fonctionne ?

Prérequis : Installez la version >=0.6.5 de DeepSpeed. Veuillez consulter les détails d'installation de DeepSpeed pour plus d'informations.

Nous examinerons d’abord l’intégration simple à utiliser via accelerate config. Sera ensuite présentée l’intégration plus flexible et riche en fonctionnalités de deepspeed config file.

Plugin DeepSpeed d'Accelerate

Sur votre machine (ou vos machines), exécutez simplement :

accelerate config

et de répondre aux questions posées. Il vous demandera si vous souhaitez utiliser un fichier de configuration pour DeepSpeed, auquel vous devez répondre non. Répondez ensuite aux questions suivantes pour générer une configuration de base de DeepSpeed. Cela génère un fichier de configuration qui sera utilisé automatiquement pour définir correctement les options par défaut lors de

accelerate launch my_script.py --args_to_my_script

Par exemple, voici comment exécuter l’exemple NLP examples/nlp_example.py (depuis la racine du dépôt) avec DeepSpeed Plugin :

Exemple de plugin DeepSpeed ZeRO Stage-2

compute_environment: LOCAL_MACHINE
deepspeed_config:
 gradient_accumulation_steps: 1
 gradient_clipping: 1.0
 offload_optimizer_device: none
 offload_param_device: none
 zero3_init_flag: true
 zero_stage: 2
distributed_type: DEEPSPEED
fsdp_config: {}
machine_rank: 0
main_process_ip: null
main_process_port: null
main_training_function: main
mixed_precision: fp16
num_machines: 1
num_processes: 2
use_cpu: false
accelerate launch examples/nlp_example.py --mixed_precision fp16

Exemple de plugin DeepSpeed ZeRO Stage-3 avec offload CPU

compute_environment: LOCAL_MACHINE
deepspeed_config:
  gradient_accumulation_steps: 1
  gradient_clipping: 1.0
  offload_optimizer_device: cpu
  offload_param_device: cpu
  zero3_init_flag: true
  zero3_save_16bit_model: true
  zero_stage: 3
distributed_type: DEEPSPEED
fsdp_config: {}
machine_rank: 0
main_process_ip: null
main_process_port: null
main_training_function: main
mixed_precision: fp16
num_machines: 1
num_processes: 2
use_cpu: false
accelerate launch examples/nlp_example.py --mixed_precision fp16

Actuellement, Accelerate prend en charge la configuration suivante via l'interface en ligne de commande :

`zero_stage`: [0] Disabled, [1] optimizer state partitioning, [2] optimizer+gradient state partitioning and [3] optimizer+gradient+parameter partitioning
`gradient_accumulation_steps`: Number of training steps to accumulate gradients before averaging and applying them.
`gradient_clipping`: Enable gradient clipping with value.
`offload_optimizer_device`: [none] Disable optimizer offloading, [cpu] offload optimizer to CPU, [nvme] offload optimizer to NVMe SSD. Only applicable with ZeRO >= Stage-2.
`offload_optimizer_nvme_path`: Decides Nvme Path to offload optimizer states. If unspecified, will default to 'none'.
`offload_param_device`: [none] Disable parameter offloading, [cpu] offload parameters to CPU, [nvme] offload parameters to NVMe SSD. Only applicable with ZeRO Stage-3.
`offload_param_nvme_path`: Decides Nvme Path to offload parameters. If unspecified, will default to 'none'.
`zero3_init_flag`: Decides whether to enable `deepspeed.zero.Init` for constructing massive models. Only applicable with ZeRO Stage-3.
`zero3_save_16bit_model`: Decides whether to save 16-bit model weights when using ZeRO Stage-3.
`mixed_precision`: `no` for FP32 training, `fp16` for FP16 mixed-precision training and `bf16` for BF16 mixed-precision training.
`deepspeed_moe_layer_cls_names`: Comma-separated list of transformer Mixture-of-Experts (MoE) layer class names (case-sensitive) to wrap ,e.g, `MixtralSparseMoeBlock`, `Qwen2MoeSparseMoeBlock`, `JetMoEAttention,JetMoEBlock` ...
`deepspeed_hostfile`: DeepSpeed hostfile for configuring multi-node compute resources.
`deepspeed_exclusion_filter`: DeepSpeed exclusion filter string when using mutli-node setup.
`deepspeed_inclusion_filter`: DeepSpeed inclusion filter string when using mutli-node setup.
`deepspeed_multinode_launcher`: DeepSpeed multi-node launcher to use, e.g. `pdsh`, `standard`, `openmpi`, `mvapich`, `mpich`, `slurm`, `nossh` (requires DeepSpeed >= 0.14.5). If unspecified, will default to `pdsh`.
`deepspeed_config_file`: path to the DeepSpeed config file in `json` format. See the next section for more details on this.

Pour pouvoir ajuster davantage d'options, vous devrez utiliser un fichier de configuration DeepSpeed.

Fichier de configuration DeepSpeed

Sur votre machine (ou vos machines), exécutez simplement :

accelerate config

et de répondre aux questions posées. Il vous demandera si vous souhaitez utiliser un fichier de configuration pour deepspeed, auquel vous répondez oui et fournissez le chemin vers le fichier de configuration deepspeed. Cela génère un fichier de configuration qui sera utilisé automatiquement pour définir correctement les options par défaut lors de

accelerate launch my_script.py --args_to_my_script

Par exemple, voici comment exécuter l’exemple NLP examples/by_feature/deepspeed_with_config_support.py (depuis la racine du dépôt) avec un fichier de configuration DeepSpeed :

Exemple de fichier de configuration DeepSpeed ZeRO Stage-2

compute_environment: LOCAL_MACHINE
deepspeed_config:
 deepspeed_config_file: /home/ubuntu/accelerate/examples/deepspeed_config_templates/zero_stage2_config.json
 zero3_init_flag: true
distributed_type: DEEPSPEED
fsdp_config: {}
machine_rank: 0
main_process_ip: null
main_process_port: null
main_training_function: main
mixed_precision: fp16
num_machines: 1
num_processes: 2
use_cpu: false

dont le contenu de zero_stage2_config.json est le suivant :

{
    "fp16": {
        "enabled": true,
        "loss_scale": 0,
        "loss_scale_window": 1000,
        "initial_scale_power": 16,
        "hysteresis": 2,
        "min_loss_scale": 1
    },
    "optimizer": {
        "type": "AdamW",
        "params": {
            "lr": "auto",
            "weight_decay": "auto",
            "torch_adam": true,
            "adam_w_mode": true
        }
    },
    "scheduler": {
        "type": "WarmupDecayLR",
        "params": {
            "warmup_min_lr": "auto",
            "warmup_max_lr": "auto",
            "warmup_num_steps": "auto",
            "total_num_steps": "auto"
        }
    },
    "zero_optimization": {
        "stage": 2,
        "allgather_partitions": true,
        "allgather_bucket_size": 2e8,
        "overlap_comm": true,
        "reduce_scatter": true,
        "reduce_bucket_size": "auto",
        "contiguous_gradients": true
    },
    "gradient_accumulation_steps": 1,
    "gradient_clipping": "auto",
    "steps_per_print": 2000,
    "train_batch_size": "auto",
    "train_micro_batch_size_per_gpu": "auto",
    "wall_clock_breakdown": false
}
accelerate launch examples/by_feature/deepspeed_with_config_support.py \
--config_name "gpt2-large" \
--tokenizer_name "gpt2-large" \
--dataset_name "wikitext" \
--dataset_config_name "wikitext-2-raw-v1" \
--block_size 128 \
--output_dir "./clm/clm_deepspeed_stage2_accelerate" \
--learning_rate 5e-4 \
--per_device_train_batch_size 24 \
--per_device_eval_batch_size 24 \
--num_train_epochs 3 \
--with_tracking \
--report_to "wandb"\

Exemple de fichier de configuration DeepSpeed pour ZeRO Stage-3 avec offload CPU

compute_environment: LOCAL_MACHINE
deepspeed_config:
 deepspeed_config_file: /home/ubuntu/accelerate/examples/deepspeed_config_templates/zero_stage3_offload_config.json
 zero3_init_flag: true
distributed_type: DEEPSPEED
fsdp_config: {}
machine_rank: 0
main_process_ip: null
main_process_port: null
main_training_function: main
mixed_precision: fp16
num_machines: 1
num_processes: 2
use_cpu: false

dont le contenu de zero_stage3_offload_config.json est le suivant :

{
    "fp16": {
        "enabled": true,
        "loss_scale": 0,
        "loss_scale_window": 1000,
        "initial_scale_power": 16,
        "hysteresis": 2,
        "min_loss_scale": 1
    },
    "optimizer": {
        "type": "AdamW",
        "params": {
            "lr": "auto",
            "weight_decay": "auto"
        }
    },
    "scheduler": {
        "type": "WarmupDecayLR",
        "params": {
            "warmup_min_lr": "auto",
            "warmup_max_lr": "auto",
            "warmup_num_steps": "auto",
            "total_num_steps": "auto"
        }
    },
    "zero_optimization": {
        "stage": 3,
        "offload_optimizer": {
            "device": "cpu",
            "pin_memory": true
        },
        "offload_param": {
            "device": "cpu",
            "pin_memory": true
        },
        "overlap_comm": true,
        "contiguous_gradients": true,
        "reduce_bucket_size": "auto",
        "stage3_prefetch_bucket_size": "auto",
        "stage3_param_persistence_threshold": "auto",
        "sub_group_size": 1e9,
        "stage3_max_live_parameters": 1e9,
        "stage3_max_reuse_distance": 1e9,
        "stage3_gather_16bit_weights_on_model_save": "auto"
    },
    "gradient_accumulation_steps": 1,
    "gradient_clipping": "auto",
    "steps_per_print": 2000,
    "train_batch_size": "auto",
    "train_micro_batch_size_per_gpu": "auto",
    "wall_clock_breakdown": false
}
accelerate launch examples/by_feature/deepspeed_with_config_support.py \
--config_name "gpt2-large" \
--tokenizer_name "gpt2-large" \
--dataset_name "wikitext" \
--dataset_config_name "wikitext-2-raw-v1" \
--block_size 128 \
--output_dir "./clm/clm_deepspeed_stage3_offload_accelerate" \
--learning_rate 5e-4 \
--per_device_train_batch_size 32 \
--per_device_eval_batch_size 32 \
--num_train_epochs 3 \
--with_tracking \
--report_to "wandb"\

Exemple de configuration ZeRO++ Vous pouvez utiliser les fonctionnalités de ZeRO++ en utilisant les paramètres de configuration appropriés. Notez que ZeRO++ est une extension de ZeRO Stage 3. Voici comment le fichier de configuration peut être modifié, d'après le tutoriel ZeRO++ de DeepSpeed :

{
    "zero_optimization": {
        "stage": 3,
        "reduce_bucket_size": "auto",

        "zero_quantized_weights": true,
        "zero_hpz_partition_size": 8,
        "zero_quantized_gradients": true,

        "contiguous_gradients": true,
        "overlap_comm": true
    }
}

Pour le partitionnement hiérarchique, la taille du partitionnement zero_hpz_partition_size doit idéalement être définie sur le nombre de GPU par nœud. (Par exemple, le fichier de configuration ci-dessus suppose 8 GPU par nœud)

Modifications importantes du code lors de l'utilisation d'un fichier de configuration DeepSpeed

  1. Optimiseurs et planificateurs DeepSpeed. Pour plus d'informations à ce sujet, consultez la documentation des Optimiseurs DeepSpeed et des Planificateurs DeepSpeed. Nous examinerons les modifications nécessaires dans le code lors de l'utilisation de ces éléments.

    a. DS Optim + DS Scheduler : le cas où les clés optimizer et scheduler sont présentes dans le fichier de configuration DeepSpeed. Dans cette situation, celles-ci seront utilisées et l'utilisateur doit utiliser accelerate.utils.DummyOptim et accelerate.utils.DummyScheduler pour remplacer les optimiseurs et planificateurs PyTorch/personnalisés dans son code. Voici l'extrait de examples/by_feature/deepspeed_with_config_support.py qui montre cela :

     # Creates Dummy Optimizer if `optimizer` was specified in the config file else creates Adam Optimizer
     optimizer_cls = (
         torch.optim.AdamW
         if accelerator.state.deepspeed_plugin is None
         or "optimizer" not in accelerator.state.deepspeed_plugin.deepspeed_config
         else DummyOptim
     )
     optimizer = optimizer_cls(optimizer_grouped_parameters, lr=args.learning_rate)
    
     # Creates Dummy Scheduler if `scheduler` was specified in the config file else creates `args.lr_scheduler_type` Scheduler
     if (
         accelerator.state.deepspeed_plugin is None
         or "scheduler" not in accelerator.state.deepspeed_plugin.deepspeed_config
     ):
         lr_scheduler = get_scheduler(
             name=args.lr_scheduler_type,
             optimizer=optimizer,
             num_warmup_steps=args.num_warmup_steps,
             num_training_steps=args.max_train_steps,
         )
     else:
         lr_scheduler = DummyScheduler(
             optimizer, total_num_steps=args.max_train_steps, warmup_num_steps=args.num_warmup_steps
         )

    b. Optimiseur personnalisé + Planificateur personnalisé : le cas où les clés optimizer et scheduler sont absentes du fichier de configuration DeepSpeed. Dans cette situation, aucune modification de code n'est nécessaire de la part de l'utilisateur et c'est le cas lors de l'utilisation de l'intégration via le plugin DeepSpeed. Dans l'exemple ci-dessus, on peut voir que le code reste inchangé si les clés optimizer et scheduler sont absentes du fichier de configuration DeepSpeed.

    c. Optimiseur personnalisé + planificateur DS : le cas où seule la clé scheduler est présente dans le fichier de configuration DeepSpeed. Dans cette situation, l'utilisateur doit utiliser accelerate.utils.DummyScheduler pour remplacer le planificateur PyTorch/personnalisé dans son code.

    d. DS Optim + planificateur personnalisé : le cas où seule la clé optimizer est présente dans le fichier de configuration DeepSpeed. Cela entraînera une erreur, car vous ne pouvez utiliser DS Scheduler que lorsque vous utilisez DS Optim.

  2. Remarquez les valeurs auto dans les fichiers de configuration DeepSpeed de l’exemple ci-dessus. Elles sont gérées automatiquement par la méthode prepare en fonction du modèle, des chargeurs de données, de l’optimiseur factice et des planificateurs factices fournis à la méthode prepare. Seuls les champs auto spécifiés dans les exemples ci-dessus sont gérés par la méthode prepare ; les autres doivent être explicitement définis par l’utilisateur.

Les valeurs auto sont calculées comme suit :

  • reduce_bucket_size: hidden_size * hidden_size
  • stage3_prefetch_bucket_size: int(0.9 * hidden_size * hidden_size)
  • stage3_param_persistence_threshold: 10 * hidden_size

Pour que la fonctionnalité auto fonctionne pour ces 3 entrées de configuration, Accelerate utilisera model.config.hidden_size ou max(model.config.hidden_sizes) comme hidden_size. Si aucune de ces valeurs n’est disponible, le lancement échouera et vous devrez définir manuellement ces 3 entrées de configuration. N’oubliez pas que les deux premières entrées de configuration sont les tampons de communication : plus ils sont grands, plus les communications seront efficaces, mais plus ils consommeront de mémoire GPU, ce qui constitue donc un compromis de performance à régler.

Points à noter lors de l'utilisation du fichier de configuration DeepSpeed

Voici un exemple de script utilisant deepspeed_config_file dans différents scénarios.

Code test.py :

from accelerate import Accelerator
from accelerate.state import AcceleratorState


def main():
    accelerator = Accelerator()
    accelerator.print(f"{AcceleratorState()}")


if __name__ == "__main__":
    main()

Scénario 1 : Fichier de configuration accelerate modifié manuellement, contenant deepspeed_config_file ainsi que d'autres entrées.

  1. Contenu de la configuration accelerate :
command_file: null
commands: null
compute_environment: LOCAL_MACHINE
deepspeed_config:
  gradient_accumulation_steps: 1
  gradient_clipping: 1.0
  offload_optimizer_device: 'cpu'
  offload_param_device: 'cpu'
  zero3_init_flag: true
  zero3_save_16bit_model: true
  zero_stage: 3
  deepspeed_config_file: 'ds_config.json'
distributed_type: DEEPSPEED
downcast_bf16: 'no'
dynamo_backend: 'NO'
fsdp_config: {}
gpu_ids: null
machine_rank: 0
main_process_ip: null
main_process_port: null
main_training_function: main
megatron_lm_config: {}
num_machines: 1
num_processes: 2
rdzv_backend: static
same_network: true
tpu_name: null
tpu_zone: null
use_cpu: false
  1. ds_config.json:
{
    "bf16": {
        "enabled": true
    },
    "zero_optimization": {
        "stage": 3,
        "stage3_gather_16bit_weights_on_model_save": false,
        "offload_optimizer": {
            "device": "none"
        },
        "offload_param": {
            "device": "none"
        }
    },
    "gradient_clipping": 1.0,
    "train_batch_size": "auto",
    "train_micro_batch_size_per_gpu": "auto",
    "gradient_accumulation_steps": 10,
    "steps_per_print": 2000000
}
  1. Sortie de accelerate launch test.py :
ValueError: When using `deepspeed_config_file`, the following accelerate config variables will be ignored:
['gradient_accumulation_steps', 'gradient_clipping', 'zero_stage', 'offload_optimizer_device', 'offload_param_device',
'zero3_save_16bit_model', 'mixed_precision'].
Please specify them appropriately in the DeepSpeed config file.
If you are using an accelerate config file, remove other config variables mentioned in the above specified list.
The easiest method is to create a new config following the questionnaire via `accelerate config`.
It will only ask for the necessary config variables when using `deepspeed_config_file`.

Scénario 2 : utilisez la solution de l'erreur pour créer une nouvelle configuration accelerate et vérifiez qu'aucune erreur d'ambiguïté n'est désormais levée.

  1. Exécuter accelerate config :
$ accelerate config
-------------------------------------------------------------------------------------------------------------------------------
In which compute environment are you running?
This machine
-------------------------------------------------------------------------------------------------------------------------------
Which type of machine are you using?
multi-GPU
How many different machines will you use (use more than 1 for multi-node training)? [1]:
Do you wish to optimize your script with torch dynamo?[yes/NO]:
Do you want to use DeepSpeed? [yes/NO]: yes
Do you want to specify a json file to a DeepSpeed config? [yes/NO]: yes
Please enter the path to the json DeepSpeed config file: ds_config.json
Do you want to enable `deepspeed.zero.Init` when using ZeRO Stage-3 for constructing massive models? [yes/NO]: yes
How many GPU(s) should be used for distributed training? [1]:4
accelerate configuration saved at ds_config_sample.yaml
  1. Contenu de la configuration accelerate :
compute_environment: LOCAL_MACHINE
deepspeed_config:
  deepspeed_config_file: ds_config.json
  zero3_init_flag: true
distributed_type: DEEPSPEED
downcast_bf16: 'no'
dynamo_backend: 'NO'
fsdp_config: {}
machine_rank: 0
main_training_function: main
megatron_lm_config: {}
num_machines: 1
num_processes: 4
rdzv_backend: static
same_network: true
use_cpu: false
  1. Sortie de accelerate launch test.py :
Distributed environment: DEEPSPEED  Backend: nccl
Num processes: 4
Process index: 0
Local process index: 0
Device: cuda:0
Mixed precision type: bf16
ds_config: {'bf16': {'enabled': True}, 'zero_optimization': {'stage': 3, 'stage3_gather_16bit_weights_on_model_save': False, 'offload_optimizer': {'device': 'none'}, 'offload_param': {'device': 'none'}}, 'gradient_clipping': 1.0, 'train_batch_size': 'auto', 'train_micro_batch_size_per_gpu': 'auto', 'gradient_accumulation_steps': 10, 'steps_per_print': inf, 'fp16': {'enabled': False}}

Scénario 3 : définir les arguments de la commande accelerate launch liés à DeepSpeed sur "auto" dans le fichier de configuration DeepSpeed et vérifier que tout fonctionne comme prévu.

  1. Nouveau ds_config.json avec "auto" pour les arguments de la commande accelerate launch DeepSpeed :
{
    "bf16": {
        "enabled": "auto"
    },
    "zero_optimization": {
        "stage": "auto",
        "stage3_gather_16bit_weights_on_model_save": "auto",
        "offload_optimizer": {
            "device": "auto"
        },
        "offload_param": {
            "device": "auto"
        }
    },
    "gradient_clipping": "auto",
    "train_batch_size": "auto",
    "train_micro_batch_size_per_gpu": "auto",
    "gradient_accumulation_steps": "auto",
    "steps_per_print": 2000000
}
  1. Sortie de accelerate launch --mixed_precision="fp16" --zero_stage=3 --gradient_accumulation_steps=5 --gradient_clipping=1.0 --offload_param_device="cpu" --offload_optimizer_device="nvme" --zero3_save_16bit_model="true" test.py :
Distributed environment: DEEPSPEED  Backend: nccl
Num processes: 4
Process index: 0
Local process index: 0
Device: cuda:0
Mixed precision type: fp16
ds_config: {'bf16': {'enabled': False}, 'zero_optimization': {'stage': 3, 'stage3_gather_16bit_weights_on_model_save': True, 'offload_optimizer': {'device': 'nvme'}, 'offload_param': {'device': 'cpu'}}, 'gradient_clipping': 1.0, 'train_batch_size': 'auto', 'train_micro_batch_size_per_gpu': 'auto', 'gradient_accumulation_steps': 5, 'steps_per_print': inf, 'fp16': {'enabled': True, 'auto_cast': True}}

Remarque :

  1. Les valeurs "auto" restantes sont gérées dans l'appel accelerator.prepare(), comme expliqué au point 2 de Important code changes when using DeepSpeed Config File.
  2. La valeur transmise lors de la création de l'objet Accelerator via Accelerator(gradient_accumulation_steps=k) n'est utilisée que lorsque gradient_accumulation_steps est auto. Lors de l'utilisation du plugin DeepSpeed, la valeur qui en provient est utilisée et elle écrase la valeur transmise lors de la création de l'objet Accelerator.

Enregistrer et charger

  1. La sauvegarde et le chargement des modèles restent inchangés pour ZeRO Stage-1 et Stage-2.

  2. Sous ZeRO Stage-3, state_dict ne contient que des espaces réservés, car les poids du modèle sont partitionnés sur plusieurs GPU. ZeRO Stage-3 propose 2 options :

    a. Enregistrer l’ensemble des poids du modèle en 16 bits pour les charger directement plus tard à l’aide de model.load_state_dict(torch.load(pytorch_model.bin)). Pour cela, définissez soit zero_optimization.stage3_gather_16bit_weights_on_model_save sur True dans le fichier de configuration DeepSpeed, soit zero3_save_16bit_model sur True dans le plugin DeepSpeed. Notez que cette option nécessite la consolidation des poids sur une seule GPU, ce qui peut être lent et gourmand en mémoire ; n’utilisez donc cette fonctionnalité que si nécessaire. Voici un extrait de examples/by_feature/deepspeed_with_config_support.py qui illustre cela :

    unwrapped_model = accelerator.unwrap_model(model)
    
    # New Code #
    # Saves the whole/unpartitioned fp16 model when in ZeRO Stage-3 to the output directory if
    # `stage3_gather_16bit_weights_on_model_save` is True in DeepSpeed Config file or
    # `zero3_save_16bit_model` is True in DeepSpeed Plugin.
    # For Zero Stages 1 and 2, models are saved as usual in the output directory.
    # The model name saved is `pytorch_model.bin`
    unwrapped_model.save_pretrained(
        args.output_dir,
        is_main_process=accelerator.is_main_process,
        save_function=accelerator.save,
        state_dict=accelerator.get_state_dict(model),
    )

    b. Pour obtenir des poids en 32 bits, enregistrez d'abord le modèle à l'aide de model.save_checkpoint(). Voici l'extrait de examples/by_feature/deepspeed_with_config_support.py qui montre cela :

    success = model.save_checkpoint(PATH, ckpt_id, checkpoint_state_dict)
    status_msg = f"checkpointing: PATH={PATH}, ckpt_id={ckpt_id}"
    if success:
        logging.info(f"Success {status_msg}")
    else:
        logging.warning(f"Failure {status_msg}")

    Cela créera les partitions du modèle et de l'optimiseur ZeRO ainsi que le script zero_to_fp32.py dans le répertoire de point de contrôle. Vous pouvez utiliser ce script pour effectuer une consolidation hors ligne. Il ne nécessite aucun fichier de configuration ni GPU. Voici un exemple de son utilisation :

    $ cd /path/to/checkpoint_dir
    $ ./zero_to_fp32.py . pytorch_model.bin
    Processing zero checkpoint at global_step1
    Detected checkpoint of type zero stage 3, world_size: 2
    Saving fp32 state dict to pytorch_model.bin (total_numel=60506624)

    Pour obtenir un modèle 32 bits pour la sauvegarde/l'inférence, vous pouvez effectuer :

    from deepspeed.utils.zero_to_fp32 import load_state_dict_from_zero_checkpoint
    
    unwrapped_model = accelerator.unwrap_model(model)
    fp32_model = load_state_dict_from_zero_checkpoint(unwrapped_model, checkpoint_dir)

    Si vous n'êtes intéressé que par le state_dict, vous pouvez procéder comme suit :

    from deepspeed.utils.zero_to_fp32 import get_fp32_state_dict_from_zero_checkpoint
    
    state_dict = get_fp32_state_dict_from_zero_checkpoint(checkpoint_dir)

    Notez que toutes ces fonctions nécessitent environ 2 fois la mémoire (RAM générale) de la taille du point de contrôle final.

Inférence ZeRO

DeepSpeed ZeRO Inference prend en charge le ZeRO stage 3 avec ZeRO-Infinity. Il utilise le même protocole ZeRO que l'entraînement, mais n'utilise ni optimiseur ni lr scheduler, et seul le stage 3 est pertinent. Avec l'intégration accelerate, il suffit de préparer le modèle et le dataloader comme indiqué ci-dessous :

model, eval_dataloader = accelerator.prepare(model, eval_dataloader)

Quelques mises en garde à connaître

  1. L'intégration actuelle ne prend pas en charge le Pipeline Parallelism de DeepSpeed.
  2. L'intégration actuelle ne prend pas en charge mpu, ce qui limite le parallélisme de tenseurs pris en charge dans Megatron-LM.
  3. L'intégration actuelle ne prend pas en charge plusieurs modèles.

DeepSpeed multi-nœuds

DeepSpeed prend en charge l’inférence et l’entraînement multi-nœuds via divers lanceurs. Vous pouvez spécifier un lanceur différent en définissant la configuration deepspeed_multinode_launcher dans l’interface en ligne de commande ou dans le fichier de configuration DeepSpeed.

Actuellement, Accelerate prend en charge la transmission de la configuration pour les lanceurs multi-nœuds DeepSpeed suivants : pdsh (par défaut), standard, openmpi, mvapich, mpich, slurm, nossh (nécessite DeepSpeed >= 0.14.5).

Veuillez consulter la documentation DeepSpeed pour plus d’informations sur les différents lanceurs. Par défaut, DeepSpeed tente d’utiliser SSH sans mot de passe depuis le nœud principal vers les autres nœuds pour exécuter la commande du lanceur. Dans cette configuration, la commande accelerate launch n’a besoin d’être exécutée que sur le nœud principal. Si vous utilisez le lanceur nossh, vous devrez exécuter la commande accelerate launch sur chaque nœud en utilisant une configuration copiée.

Ressources DeepSpeed

La documentation relative aux éléments internes de deepspeed peut être consultée ici.

Articles :

Enfin, n’oubliez pas que Accelerate intègre uniquement DeepSpeed. Par conséquent, si vous rencontrez des problèmes ou avez des questions concernant l’utilisation de DeepSpeed, veuillez ouvrir un ticket sur GitHub DeepSpeed.

Pour ceux qui s'intéressent aux similitudes et aux différences entre FSDP et DeepSpeed, consultez le guide des concepts ici !

Update on GitHub