Aller au contenu principal

Chapitre 2 : Exigences Computationnelles

Calcul de la Mémoire GPU et des Coûts d'Entraînement​

Comprendre les exigences computationnelles pour le fine-tuning est crucial pour planifier vos projets et choisir la bonne approche.


Composants de la Mémoire GPU​

Pendant l'entraînement, la mémoire GPU est consommée par quatre composants principaux :

1. Poids du Modèle​

Les paramètres du modèle lui-même.

2. Gradients​

Même taille que les poids—stocke le gradient pour chaque paramètre.

3. États de l'Optimiseur​

AdamW stocke 2 états (momentum, variance) par paramètre.

4. Activations​

Valeurs intermédiaires nécessaires pour la rétropropagation.


Formule de Calcul de la Mémoire​

Formule de Base​

Mémoire (octets) = Paramètres × Précision × Multiplicateur

Où le Multiplicateur pour l'entraînement :
- Inférence : 1
- Entraînement AdamW : 4-6 (poids + gradients + 2 états de l'optimiseur + activations)

Tailles de Précision​

PrécisionOctets par Paramètre
float324
bfloat162
float162
int81
int40.5

Exigences de Mémoire pour le Fine-Tuning Complet​

Exemple : Modèle de 7B Paramètres​

# Paramètres : 7 milliards
parameters = 7_000_000_000

# Avec float32 (pleine précision)
weights_fp32 = parameters * 4 # 28 GB
gradients_fp32 = parameters * 4 # 28 GB
optimizer_fp32 = parameters * 4 * 2 # 56 GB (2 états)
# Total : ~112 GB ❌ Trop pour la plupart des GPU

# Avec bfloat16 + précision mixte
weights_bf16 = parameters * 2 # 14 GB
gradients_bf16 = parameters * 2 # 14 GB
optimizer_fp32 = parameters * 4 * 2 # 56 GB (conservé en fp32)
# Total : ~84 GB ⚠️ Nécessite toujours A100-80GB

# Avec checkpointing des gradients + bf16
# Activations réduites de ~30%
# Total : ~60-70 GB

Tableau des Exigences de Mémoire​

Taille du ModèleFT Complet (fp32)FT Complet (bf16)Avec Grad Ckpt
1B~16 GB~12 GB~8 GB
7B~112 GB~84 GB~60 GB
13B~208 GB~156 GB~110 GB
70B~1.1 TB~840 GB~600 GB

Réduction des Exigences de Mémoire​

1. Entraînement en Précision Mixte​

training_args = TrainingArguments(
bf16=True, # Utiliser bfloat16
)

Réduit la mémoire des poids et des gradients d'environ 50 %.

2. Checkpointing des Gradients​

training_args = TrainingArguments(
gradient_checkpointing=True,
)
# OU
model.gradient_checkpointing_enable()

Échange le calcul contre la mémoire—recalcule les activations pendant la passe arrière.

3. Accumulation des Gradients​

training_args = TrainingArguments(
per_device_train_batch_size=1,
gradient_accumulation_steps=16,
# Taille de lot effective = 1 * 16 = 16
)

Les lots plus petits utilisent moins de mémoire ; accumulez les gradients pour simuler des lots plus grands.

4. Optimiseurs Efficaces en Mémoire​

# Adam 8 bits (nécessite bitsandbytes)
training_args = TrainingArguments(
optim="adamw_8bit",
)

# OU Adafactor (sans momentum)
training_args = TrainingArguments(
optim="adafactor",
)

5. DeepSpeed ZeRO​

# deepspeed_config.json
{
"zero_optimization": {
"stage": 2, # Partitionner les gradients et les états de l'optimiseur
}
}

# Pendant l'entraînement
training_args = TrainingArguments(
deepspeed="deepspeed_config.json",
)

Étapes ZeRO :

  • Étape 1 : Partitionner les états de l'optimiseur
  • Étape 2 : + Partitionner les gradients
  • Étape 3 : + Partitionner les poids du modèle (permet d'entraîner des modèles plus grands que la mémoire GPU)

Recommandations Pratiques pour GPU​

Entraînement sur un Seul GPU​

GPUVRAMModèle Max (FT Complet)Modèle Max (Efficace)
RTX 309024 GB1B3B
RTX 409024 GB1B3B
A100-40GB40 GB3B7B
A100-80GB80 GB7B13B
H10080 GB7B13B

Entraînement Multi-GPU​

# Distribution automatique avec accelerate
from accelerate import Accelerator

accelerator = Accelerator()
model, optimizer, dataloader = accelerator.prepare(
model, optimizer, dataloader
)
ConfigurationVRAM CombinéeModèle Max (Efficace)
2× A100-40GB80 GB7-13B
4× A100-80GB320 GB30-40B
8× H100640 GB70B

Estimation du Temps d'Entraînement​

Facteurs Affectant le Temps d'Entraînement​

Temps d'Entraînement = (Taille du Jeu de Données × Époques) / (Taille de Lot × Débit)

Exemples de Débit (tokens/seconde)​

ModèleGPUDébit
7BA100-40GB~1,000 tokens/s
7BH100~2,000 tokens/s
13BA100-80GB~500 tokens/s
70B8× H100~800 tokens/s

Exemple de Calcul du Temps​

# Jeu de données : 10,000 exemples, 512 tokens chacun
total_tokens = 10_000 * 512 = 5_120_000

# Entraînement : 3 époques
total_training_tokens = 5_120_000 * 3 = 15_360_000

# Débit : 1,000 tokens/seconde
training_time_seconds = 15_360_000 / 1_000 = 15,360 secondes
training_time_hours = 15_360 / 3_600 = 4.3 heures

Estimation des Coûts Infonuagiques​

Tarification des GPU (Approximative)​

GPUÀ la Demande ($/hr)Spot ($/hr)
T4$0.50$0.15
A10G$1.50$0.45
A100-40GB$4.00$1.20
A100-80GB$6.00$1.80
H100$8.00$2.40

Exemple de Calcul de Coût​

# Entraînement d'un modèle 7B
# Temps : 4 heures sur A100-40GB
# Coût : 4 × $4.00 = $16 (à la demande)
# Coût : 4 × $1.20 = $4.80 (spot)

# Avec expérimentation (5 exécutions)
# Total : $80 (à la demande) ou $24 (spot)

Profilage de la Mémoire​

Vérifier l'Utilisation Actuelle de la Mémoire​

import torch

# Mémoire allouée actuelle
allocated = torch.cuda.memory_allocated() / 1024**3
print(f"Allouée : {allocated:.2f} GB")

# Utilisation maximale de la mémoire
peak = torch.cuda.max_memory_allocated() / 1024**3
print(f"Pic : {peak:.2f} GB")

# Réinitialiser les statistiques de pic
torch.cuda.reset_peak_memory_stats()

Estimer Avant l'Entraînement​

def estimate_memory(model, batch_size, seq_len, precision="bf16"):
"""Estimer les exigences de mémoire d'entraînement."""
param_count = sum(p.numel() for p in model.parameters())

# Octets par paramètre en fonction de la précision
bytes_per_param = 2 if precision == "bf16" else 4

# Poids du modèle
weights_gb = (param_count * bytes_per_param) / 1024**3

# Gradients (même que les poids)
gradients_gb = weights_gb

# États de l'optimiseur (AdamW : 2 états en fp32)
optimizer_gb = (param_count * 4 * 2) / 1024**3

# Activations (estimation approximative)
activation_gb = (batch_size * seq_len * 4096 * 4) / 1024**3 # Approximatif

total_gb = weights_gb + gradients_gb + optimizer_gb + activation_gb

print(f"Poids : {weights_gb:.2f} GB")
print(f"Gradients : {gradients_gb:.2f} GB")
print(f"Optimiseur : {optimizer_gb:.2f} GB")
print(f"Activations : ~{activation_gb:.2f} GB")
print(f"Total : ~{total_gb:.2f} GB")

return total_gb

Liste de Vérification pour l'Optimisation​

□ Activer la précision mixte (bf16/fp16)
□ Activer le checkpointing des gradients
□ Utiliser l'accumulation des gradients pour des tailles de lot effectives plus grandes
□ Envisager des optimiseurs 8 bits
□ Utiliser DeepSpeed pour le multi-GPU
□ Surveiller la mémoire avec le profilage
□ Utiliser des instances spot pour économiser sur les coûts

Points Clés​

✅ Le fine-tuning complet nécessite ~4-6x la taille du modèle en mémoire GPU

✅ Un modèle 7B nécessite 60-80GB pour le fine-tuning complet

✅ La précision mixte et le checkpointing des gradients réduisent considérablement la mémoire

✅ L'entraînement multi-GPU permet des modèles plus grands

✅ Les coûts infonuagiques peuvent être réduits de 60-70% avec des instances spot

✅ Toujours profiler la mémoire avant de s'engager dans de longues sessions d'entraînement


Prochaines Étapes​

Continuez vers Chapitre 3 : Oubli Catastrophique pour en savoir plus sur la rétention des connaissances pendant le fine-tuning.


Vérification Rapide​

Avant de continuer, assurez-vous de pouvoir répondre :

  1. Quels sont les quatre principaux composants consommant de la mémoire GPU pendant l'entraînement ?
  2. Quelle quantité de mémoire un modèle 7B nécessite-t-il pour un fine-tuning complet avec bf16 ?
  3. Quel est le but de l'accumulation des gradients ?