RL efficace en mémoire
Nous sommes ravis de présenter un apprentissage par renforcement (RL) plus efficace dans Unsloth avec plusieurs avancées algorithmiques :
Allongements de contexte augmentés de 1,2 à 1,7x sans ralentissement et sans utilisation mémoire supplémentaire !
Exécutions d'entraînement RL 10 % plus rapides avec des noyaux retravaillés et des mouvements de données asynchrones
2x plus rapide
torch.compilefois pendant le chargement du modèle
Unsloth déjà augmente la vitesse d'entraînement RL, la fenêtre de contexte et réduit l'utilisation de la VRAM de 50–90 % par rapport à toutes les autres configurations avec FA2, mais maintenant Standby d'Unsloth améliore cela encore davantage. Notre fonctionnalité Standby limite de manière unique la dégradation de la vitesse par rapport à d'autres implémentations et rend parfois l'entraînement encore plus rapide !
Maintenant, Qwen3-32B LoRA 16 bits peut atteindre des longueurs de contexte de 6 144 contre 3 600 (1,7x plus long) auparavant sur un GPU 1xH100 80GB. Llama-3.1-8B QLoRA 4 bits peut atteindre 47 500 longueurs contre 42 000 auparavant (1,13x plus long).
Nous avons rendu les exécutions RL 10 % plus rapides grâce à diverses optimisations des noyaux, et avons supprimé le canal de communication LoRA entre le CPU et le GPU lors du passage du mode entraînement au mode inférence. Enfin, nous avons utilisé des torch.compile indicateurs pour rendre le rollout de vLLM 10 % plus rapide, et réduit le temps de compilation par 2x.
✨Comment activer les optimisations
Pour permettre la Standby d'Unsloth fonctionnalité, définissez la variable d'environnement UNSLOTH_VLLM_STANDBY avant tout import Unsloth. Ensuite définissez gpu_memory_utilization = 0.95 et c'est tout !
import os
os.environ["UNSLOTH_VLLM_STANDBY"] = "1"
from unsloth import FastLanguageModel
import torch
model, tokenizer = FastLanguageModel.from_pretrained(
model_name = "unsloth/Qwen3-8B-Base",
max_seq_length = 2048, # Peut augmenter pour des traces de raisonnement plus longues
load_in_4bit = False, # False pour LoRA 16bit
fast_inference = True,
max_lora_rank = 32, # Rang plus grand = plus intelligent, mais plus lent
gpu_memory_utilization = 0.95,
)🎓Plus besoin de gpu_memory_utilization!
gpu_memory_utilization!Avec les nouvelles améliorations RL d'Unsloth, vous n'avez JAMAIS à vous soucier d'ajuster ou de définir gpu_memory_utilization à nouveau - définissez-le simplement à 90 % ou 95 % d'utilisation du GPU - 100 % ne fonctionnera malheureusement pas car un peu d'espace est nécessaire pour les petits tenseurs. Auparavant, il fallait l'ajuster de 30 % à 95 % - plus maintenant ! Mettez-le au maximum et Unsloth s'occupe du reste !
⁉️Pourquoi le RL utilise-t-il autant de mémoire ?
GRPO (et de nombreuses variantes de RL) s'appuient fortement sur la génération qui est principalement assurée par vLLM. Mais cela a un coût élevé car cela nécessite constamment mémoire GPU pour les poids, les activations et le cache KV.
L'inférence prend beaucoup de VRAM

Alors que l'entraînement utilise aussi de la VRAM !

Cela signifie que le RL doit garder 2 ensembles de VRAM / mémoire sur le GPU en même temps :
Moteur d'inférence (contient les poids du modèle, le cache KV)
Moteur d'entraînement (contient les poids du modèle, les activations, les gradients, les états de l'optimiseur)
Les frameworks RL actuels doivent répartir 50/50 pour un GPU de 80 Go avec 50 % pour l'inférence et 50 % pour l'entraînement. Et déplacer les poids du mode entraînement au mode inférence peut prendre pas mal de temps.
Poids du modèle
16 Go
16 Go
Cache KV
24 Go
Activations, gradients, états de l'optimiseur
24 Go
Les versions précédentes d'Unsloth optimisent déjà intelligemment ce qui précède, car nous partageons directement l'espace de poids de vLLM ce qui élimine la double consommation mémoire des poids du modèle. Cela libère par exemple 16 Go d'espace qui peut être utilisé pour augmenter la longueur du contexte ou la vitesse de génération. De plus, nous n'avons pas besoin d'effectuer des mouvements de mémoire, ce qui accélère l'entraînement.
Poids du modèle
16 Go PARTAGÉS
<<< PARTAGÉ
Cache KV
24 Go + 8 Go= 32 Go
Activations, gradients, états de l'optimiseur
24 Go + 8 Go=32 Go
🦥Unsloth Standby
Mais nous pouvons aller plus loin - nous remarquons d'abord que le RL fait inférence puis entraînement puis inférence puis entraînement, etc.

Cela signifie que l'espace mémoire pour l'inférence et l'entraînement peut en théorie être réutilisé, puisque l'inférence et l'entraînement sont des modes séparés - c'est là que la fonction de mode veille de vLLM entre en jeu, qui a 2 options :
level = 1copie les poids vers le CPU et supprime le cache KVlevel = 2supprime les poids et supprime le cache KV
Mais rappelons qu'avec Unsloth nous partageons l'espace mémoire de vLLM pour les poids - cela signifie que nous avons besoin d'une nouvelle façon de supprimer le cache KV, et d'ignorer la suppression des poids, et nous appelons cela Unsloth Standby.
Poids du modèle
16 Go PARTAGÉS
<<< PARTAGÉ
Polyvalent
Espace de 64 Go
Cache KV
Activations, gradients, états de l'optimiseur
Pour activer cela, ajoutez simplement ce qui suit à toutes les exécutions d'entraînement RL / GRPO avant tout import Unsloth :
🧪Expériences de performance
Ici vous découvrirez comment nous avons mesuré l'utilisation de la mémoire et la longueur de contexte pour GRPO. Notez que nous faisons 2 générations par prompt car pour que GRPO fonctionne, nous avons besoin d'au moins 2 générations pour pouvoir calculer la moyenne d'échantillon et la variance. Sans 2 générations, l'écart type d'un seul échantillon est 0. Cela provoque que les avantages qui utilisent ceci : (reward - mean)/std soient indéfinis.
Cela signifie que pour GRPO spécifiquement, une longueur de contexte maximale de 6 144 pour Qwen-3 32B correspond en fait à 6 144 multiplié par 2 générations, soit 12 288 en longueur.
Nous fournissons des expériences pour Llama-3.1 8B sur LoRA (16 bits) et QLoRA (4 bits) ci‑dessous :

Si vous remarquez des différences de temps d'entraînement, ce n'est pas grand‑chose. Dans notre comparaison à armes égales, nous avons observé des ralentissements de temps d'entraînement <1 % ou même des accélérations pouvant être attribuées à la marge d'erreur.
Nous émettons aussi l'hypothèse que des accélérations sont possibles en raison d'une moindre pression mémoire, donc il pourrait y avoir moins de nettoyage mémoire côté allocateur CUDA.

Dans l'image ci‑dessous, vous voyez la différence entre le mode de base et le mode standby sur un seul GPU T4 pour Qwen 3 4B. Nous pouvons pousser la gpu_memory_utilisation de vllm jusqu'à 0,95 sans craindre que cela n'affecte l'entraînement. Cela signifie que vous pouvez adapter des séquences de longueur de contexte plus élevée et traiter plus de séquences. Dans le premier cas, par exemple, nous avons suffisamment de mémoire pour adapter et traiter des séquences de longueur 32K si l'entraînement le permet, alors qu'auparavant, toute entrée plus longue que 2K risquait de ne pas tenir et de provoquer des OOM (out of memory).
standby True
vllm_gpu_util 0.95
num_gen 2
grad_acc_steps 2
S'exécute pendant 40 étapes / 40 minutes
14,5 Gio (défini par vllm_gpu_util)
Suffisant pour tenir dans 32K KVCache avec des chunks de 2-4K ou par exemple 16K KVCache + chunks de 16K
standby True
vllm_gpu_util 0.9
num_gen 2
grad_acc_steps 2
S'exécute 32 étapes en 40 m
13,8 Gio (défini par…)
Approx suffisamment pour tenir dans ~28K KVCache avec des chunks de 2-4K ou par exemple 15K KVCache + chunks de 15K
standby False
vllm_gpu_util 0.9
num_gen 2
grad_acc_steps 2
le modèle se charge mais ne peut pas entraîner car même une taille de batch de 1 ne rentre pas
OOM
standby False
vllm_gpu_util 0.8
num_gen 2
grad_acc_steps 2
le modèle se charge mais ne peut pas entraîner car même une taille de batch de 1 ne rentre pas
OOM
standby False
vllm_gpu_util 0.7
num_gen 2
grad_acc_steps 2
S'entraîne correctement
28 étapes prennent 39 min
~15,1 Gio
toute entrée légèrement plus longue entraînera un OOM sur Colab
standby True
vllm_gpu_util 0.7
num_gen 2
grad_acc_steps 2
S'entraîne correctement
29 étapes prennent 40 min
13 Gio mais la plupart du temps autour de 10-11 Go
Avec la même config, nous économisons 2 Gio soit 15 % de mémoire ici. Peut être plus élevé pour des séquences plus longues
Expériences H100
Qwen2.5-14B-Instruct
NVIDIA H100 80GB PCIe
32,768
8
4
Dans nos résultats dépliables ci‑dessous, vous pouvez voir qu'il y a une différence de 9 Gio dans la mémoire de pointe utilisée (notez que 90 % du temps, l'utilisation mémoire du GPU est égale à la mémoire de pointe dans notre cas). Pour mettre les choses en perspective, en utilisant TRL et LoRA nous avons pu affiner seulement un modèle de 8 milliards de paramètres avec une longueur de contexte maximale de 1 024 (32x moins). Toute chose avec une longueur de séquence plus élevée (avec configuration similaire) entraîne l'échec du processus avec un OOM.
L'image ci‑dessous montre comment le mode standby se compare à l'entraînement sans standby avec Unsloth. Elle est moyennée sur 3 exécutions pour s'assurer que les métriques ne sont pas bruitées. En fait, si vous zoomez suffisamment, vous verrez que l'activation du standby le rend aussi plus rapide, probablement en raison d'une moindre pression mémoire comme discuté précédemment.

Expériences précédentes sur A100 40GB
Dans nos expériences précédentes sur GPU A100 40GB avec Qwen-2.5-3b-instruct et 8 générations par échantillon, nous avons observé que sans standby, l'entraînement GRPO (modèle chargé en 16 bits, LoRA, seuls les poids entraînables) ne permettait d'ajuster que des longueurs de séquence de 6K. Avec notre fonctionnalité standby, nous avons pu tenir 10K et au‑delà ! Pour comparaison, TRL ne peut vous offrir des longueurs de contexte que jusqu'à 1K tout en conservant la même taille de batch.

🎉Autres optimisations
Nous sélectionnons désormais de meilleurs drapeaux de compilation et réduisons les temps de compilation de 50 % ou plus. Nous avons aussi réussi à patcher dynamiquement toute version de vLLM pour gérer gc.collect mieux pour des raisons de compatibilité descendante, comme inspiré de cette pull request vLLM. Cela réduit les temps de compilation de 2 minutes à moins de 40 secondes.
Nous avons également optimisé torch.compile les indicateurs et essayé d'activer certains flags - malheureusement combo_kernels et multi_kernel n'a pas pu fonctionner correctement sur vLLM 0.10 et Torch 2.8/2.9 nightly et coordinate_descent_tuning a rendu l'autotuning de tous les noyaux considérablement plus lent. Cela compilait auparavant en moins d'une minute, mais l'activer prenait plus de 13 minutes et plus, avec des gains de performances minimes.
📚Cahiers GRPO
Tous nos notebooks GRPO ont Unsloth Standby activé par défaut et toutes les optimisations ! Voir https://docs.unsloth.ai/get-started/unsloth-notebooks pour tous nos notebooks GRPO, ou essayez ce qui suit :
Qwen3 (4B) - GRPO LoRA avancé
DeepSeek-R1-0528-Qwen3 (8B) (pour des cas d'utilisation multilingues)
Llama 3.2 (3B) - GRPO LoRA avancé
Mis à jour
Ce contenu vous a-t-il été utile ?

