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écision | Octets par Paramètre |
|---|---|
| float32 | 4 |
| bfloat16 | 2 |
| float16 | 2 |
| int8 | 1 |
| int4 | 0.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èle | FT 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
| GPU | VRAM | Modèle Max (FT Complet) | Modèle Max (Efficace) |
|---|---|---|---|
| RTX 3090 | 24 GB | 1B | 3B |
| RTX 4090 | 24 GB | 1B | 3B |
| A100-40GB | 40 GB | 3B | 7B |
| A100-80GB | 80 GB | 7B | 13B |
| H100 | 80 GB | 7B | 13B |
Entraînement Multi-GPU
# Distribution automatique avec accelerate
from accelerate import Accelerator
accelerator = Accelerator()
model, optimizer, dataloader = accelerator.prepare(
model, optimizer, dataloader
)
| Configuration | VRAM Combinée | Modèle Max (Efficace) |
|---|---|---|
| 2× A100-40GB | 80 GB | 7-13B |
| 4× A100-80GB | 320 GB | 30-40B |
| 8× H100 | 640 GB | 70B |
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èle | GPU | Débit |
|---|---|---|
| 7B | A100-40GB | ~1,000 tokens/s |
| 7B | H100 | ~2,000 tokens/s |
| 13B | A100-80GB | ~500 tokens/s |
| 70B | 8× 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 :
- Quels sont les quatre principaux composants consommant de la mémoire GPU pendant l'entraînement ?
- Quelle quantité de mémoire un modèle 7B nécessite-t-il pour un fine-tuning complet avec bf16 ?
- Quel est le but de l'accumulation des gradients ?