Entraînement LLM 3x plus rapide avec les noyaux Unsloth + Packing

Apprenez comment Unsloth augmente le débit d'entraînement et élimine le gaspillage de padding pour l'ajustement.

Unsloth prend désormais en charge jusqu'à 5× plus rapide (typiquement 3x) l'entraînement avec nos nouveaux noyaux RoPE et MLP Triton, plus notre nouveau empaquetage automatique intelligent. Les nouveaux noyaux et fonctionnalités d'Unsloth augmentent non seulement la vitesse d'entraînement, mais réduisent également l'utilisation de la VRAM (30% - 90%) sans perte de précision. Unsloth GitHubarrow-up-right Cela signifie que vous pouvez désormais entraîner des LLMs comme Qwen3-4B non seulement sur seulement 3 Go de VRAM, mais aussi 3x plus rapidement.

Notre auto sans remplissage l'empaquetage non contaminé est activé intelligemment pour toutes les sessions d'entraînement sans aucun changement, et pour tous les backends d'attention rapide (FlashAttention 3, xFormers, SDPA). Benchmarks montrent que les pertes d'entraînement correspondent aux exécutions sans empaquetage exactement.

  • Noyau Triton RoTation QK 2,3x plus rapide noyau Triton fusionné avec prise en charge de l'empaquetage

  • Noyaux SwiGLU, GeGLU mis à jour avec indexation int64 pour un contexte long

  • Empaquetage non contaminé 2,5x à 5x plus rapide avec les backends xformers, SDPA, FA3

  • 2,1x plus rapide sans remplissage, 50% de VRAM en moins, 0% de changement de précision

  • Unsloth bénéficie désormais également d'une meilleure stabilité de la perte SFT et d'une utilisation GPU plus prévisible.

  • Cette nouvelle mise à niveau fonctionne pour toutes les méthodes d'entraînement par ex. fine-tuning complet, préentraînement, etc.

🥁Noyau Triton RoPE QK fusionné avec empaquetage

En décembre 2023, nous avons présenté un noyau RoPE codé en Triton dans le cadre du lancement d'Unsloth. En mars 2024, un membre de la communauté a rendu l'entraînement de bout en bout 1-2% plus rapide en optimisant le noyau RoPE pour permettre de lancer un bloc pour un groupe de têtes. Voir PR 238arrow-up-right.

Un problème était que pour chaque Q et K, il y avait 2 noyaux Triton. Nous les avons maintenant fusionnés en 1 noyau Triton, et activé la RoPE de longueur variable, ce qui était impératif pour le sans remplissage et la prise en charge de l'empaquetage. Cela rend le noyau RoPE dans les micro-benchmarks 2,3x plus rapide sur des longueurs de contexte plus longues, et 1,9x plus rapide sur des longueurs de contexte plus courtes.

Nous avons également éliminé toutes les copies et opérations de transposition contiguës, et donc RoPE est désormais entièrement en place, réduisant encore la mémoire GPU. Notez que pour la passe arrière, nous observons que sin1 = -sin1 puisque :

🚃Indexation Int64 pour les noyaux Triton

Lors d'un entraînement sur contexte long de 500K que nous avons introduit dans 500K Context Training, nous avions des erreurs CUDA hors limites. C'était parce que les noyaux MLP pour SwiGLU, GeGLU utilisaient une indexation int32 qui est par défaut dans Triton et CUDA.

Nous ne pouvons pas simplement faire tl.program_id(0).to(tl.int64) car l'entraînement sera légèrement plus lent en raison de l'indexation int64. Nous en faisons plutôt une LONG_INDEXING: tl.constexpr variable afin que le compilateur Triton puisse la spécialiser. Cela permet aux exécutions de contexte courts et longs de bien fonctionner !

🧮Pourquoi le remplissage est-il nécessaire & accélération mathématique

Les ordinateurs et GPU ne peuvent pas traiter des ensembles de données de longueurs différentes, nous devons donc les remplir avec des 0. Cela provoque du gaspillage. Supposons que nous ayons un ensemble de données composé à 50% de courtes séquences S et à 50% de longues séquences L, alors dans le pire des cas, le remplissage fera que l'utilisation des tokens sera batchsize×L\text{batchsize} \times L puisque la longueur de la séquence la plus longue domine.

En empaquetant plusieurs exemples dans un seul tenseur unidimensionnel long, nous pouvons éliminer une quantité significative de remplissage. En fait, nous obtenons l'utilisation de tokens ci-dessous :

Token Usage=batchsize2L+batchsize2S\text{Token Usage} = \frac{\text{batchsize}}{2}L+\frac{\text{batchsize}}{2}S

Par quelques calculs et algèbre, nous pouvons déterminer l'accélération via :

Speedup=batchsize×Lbatchsize2L+batchsize2S=2LL+S\text{Speedup} = \frac{\text{batchsize} \times L}{\frac{\text{batchsize}}{2}L+\frac{\text{batchsize}}{2}S} = 2 \frac{L}{L + S}

En supposant S0S\rightarrow0 alors nous obtenons un gain théorique de 2x car 2LL+0=22 \frac{L}{L + 0} = 2

En changeant le ratio de 50% de courtes séquences, et en supposant que nous ayons PLUS de courtes séquences, par exemple 20% de longues séquences et 80% de courtes séquences, nous obtenons L0.2L+0.8SL0.2L=5\frac{L}{0.2L + 0.8S}\rightarrow\frac{L}{0.2L}=5 donc un entraînement 5x plus rapide ! Cela signifie que l'accélération de l'empaquetage dépend de la proportion de lignes courtes dans votre ensemble de données (plus il y a de courtes, plus c'est rapide).

🎬Sans remplissage par défaut

En plus des gains de débit importants disponibles lors du réglage de packing = True dans votre SFTConfig , nous allons utilise automatiquement le batching sans remplissage afin de réduire le gaspillage dû au remplissage, d'améliorer le débit et d'augmenter les tokens/s de débit, tout en obtenant exactement la même perte que dans la version précédente d'Unsloth.

Par exemple, pour Qwen3-8B et Qwen3-32B, nous constatons une diminution de l'utilisation mémoire de 60%, une vitesse 2x supérieure et des courbes de perte et de norme de gradient identiques !

♠️Empaquetage non contaminé : entraînement 2-5x plus rapide

Les jeux de données réels peuvent contenir des longueurs de séquence différentes, donc augmenter la taille de lot à 32 par exemple entraînera du remplissage, rendant l'entraînement plus lent et utilisant plus de VRAM.

circle-check

Lorsque nous empaquetons plusieurs échantillons dans un seul tenseur unidimensionnel, nous conservons les métadonnées de longueur de séquence afin de bien masquer les échantillons, sans fuir l'attention entre eux. Nous avons également besoin du noyau RoPE décrit dans New 3x Faster Training pour permettre la réinitialisation des identifiants de position.

4 exemples sans empaquetage gaspillent de l'espace

L'empaquetage non contaminé crée un schéma d'attention correct

En changeant le ratio de 50% de courtes séquences, et en supposant que nous ayons PLUS de courtes séquences, par ex. 20% de longues séquences et 80% de longues séquences, nous obtenons L0.2L+0.8SL0.2L=5\frac{L}{0.2L + 0.8S}\rightarrow\frac{L}{0.2L}=5 donc un entraînement 5x plus rapide ! Cela signifie que l'accélération de l'empaquetage dépend de la proportion de lignes courtes dans votre ensemble de données (plus il y a de courtes, plus c'est rapide).

🏖️Analyse et benchmarks

Pour démontrer les diverses améliorations lors de l'entraînement avec nos nouveaux noyaux et données empaquetées, nous avons exécuté des runs de fine-tuning avec Qwen3-32B, Qwen3-8B, Llama 3 8B sur le yahma/alpaca-cleaned jeu de données et mesuré diverses pertes d'entraînement débit et métriques d'efficacité. Nous avons comparé nos nouvelles exécutions avec un run d'entraînement optimisé standard avec nos propres noyaux/optimisations activés et des noyaux comme Flash Attention 3 (FA3) activés. Nous avons fixé max_length = 1024 et fait varier la taille de lot dans {1, 2, 4, 8, 16, 32}. Cela permet au nombre maximal de tokens par lot de varier dans {1024, 2048, 4096, 8192, 16K, 32K}.

Ce qui précède montre comment le débit d'entraînement en tokens par seconde (tokens/s) varie pour le nouvel Unsloth en fonction de la taille de lot. Cela se traduit par l'entraînement de votre modèle sur une époque de votre jeu de données 1,7-3x plus rapide (parfois même 5x ou plus)! Ces gains seront plus prononcés s'il y a beaucoup de courtes séquences dans vos données et si vous avez des runs d'entraînement plus longs, comme décrit dans New 3x Faster Training

Ce qui précède montre le pourcentage moyen de tokens par lot qui sont valides (c.-à-d. non remplissage). À mesure que la longueur de la taille de lot augmente, beaucoup plus de tokens de remplissage apparaissent dans le cas non empaqueté, tandis que nous obtenons une grande efficacité d'empaquetage dans le cas empaqueté quel que soit la longueur de séquence maximale.

Notez que, puisque la logique de batching ajuste les lots à la longueur de séquence maximale vue dans le lot, lorsque la taille de lot est 1, les données non empaquetées sont toutes des tokens valides (c.-à-d. pas de remplissage). Cependant, à mesure que davantage d'exemples sont ajoutés au lot, le remplissage augmente en moyenne, atteignant presque 50% de remplissage avec une taille de lot de 8 ! Notre implémentation d'empaquetage d'échantillons élimine ce gaspillage.

Le premier graphique (ci-dessus) trace la progression sur yahma/alpaca-cleaned avec max_length = 2048, Unsloth nouveau avec empaquetage + noyaux (bordeaux) vs. Unsloth ancien (gris). Les deux sont entraînés avec max_steps = 500, mais nous affichons l'axe des x en temps réel. Remarquez que nous entraînons près de 40% d'une époque dans le cas empaqueté avec le même nombre d'étapes (et seulement un peu plus de temps réel) qu'il n'en faut pour entraîner moins de 5% d'une époque dans le cas non empaqueté.

De même, le 2ème graphique (ci-dessus) trace la perte des mêmes runs, cette fois tracée avec les étapes d'entraînement sur l'axe des x. Remarquez que les pertes correspondent en échelle et en tendance, mais la perte dans le cas empaqueté est moins variable puisque le modèle voit plus de tokens par étape d'entraînement.

Comment activer l'empaquetage ?

Mettez d'abord Unsloth à jour et le sans remplissage est activé par défaut ! Ainsi, tout l'entraînement est immédiatement 1,1 à 2x plus rapide avec au moins 30% de mémoire en moins et aucune modification de la courbe de perte !

Nous prenons également en charge Flash Attention 3 via Xformers, le support SDPA, Flash Attention 2, et cela fonctionne sur les anciennes GPU (Tesla T4, RTX 2080) et les nouvelles comme les H100, B200, etc. ! L'empaquetage d'échantillons fonctionne indépendamment du choix du backend d'attention ou de la famille de modèles, profitez donc des mêmes accélérations qu'auparavant avec ces implémentations d'attention rapides !

Si vous souhaitez activer l'empaquetage explicite, ajoutez simplement packing = True pour permettre jusqu'à 5x d'entraînement plus rapide !

circle-exclamation

Tous nos notebooks sont automatiquement plus rapides (aucune action requise). Voir Notebooks Unsloth

Merci ! Si cela vous intéresse, consultez notre 500K Context Training blog, RL efficace en mémoire blog et Long Context gpt-oss blog pour plus de sujets sur les noyaux et les gains de performance !

Mis à jour

Ce contenu vous a-t-il été utile ?