Stockage pour les clusters d'IA : NFS, BeeGFS, Lustre et la question du stockage objet

Le stockage partagé est un aspect souvent négligé des clusters d'entraînement distribués, jusqu'à ce qu'il soit responsable d'une utilisation des GPU plafonnée à 40 %. À ce stade, son remplacement s'avère complexe : chaque script d'entraînement intègre des hypothèses, chaque point de contrôle est dans un format dont la migration peut être compromise, et le cluster est en production. Le choix du stockage doit donc être mûrement réfléchi avant même l'installation du deuxième nœud d'entraînement.

Voici la partie stockage de la série K. Il s'agit d'une présentation destinée aux acheteurs et aux architectes, et non d'un guide pour administrateurs système ; l'objectif est de permettre aux clients de Kentino de choisir en toute connaissance de cause entre NFS, BeeGFS, Lustre et les systèmes de stockage d'objets, et d'être honnêtes sur la solution dont ils ont réellement besoin.

Pourquoi le stockage partagé est un goulot d'étranglement silencieux

Un programme d'entraînement à nœud unique lit son jeu de données depuis un disque NVMe local et y écrit les points de contrôle. Rien à signaler. Dès qu'un deuxième nœud se connecte, deux choses changent :

  1. Chaque nœud lit le même ensemble de données. Les octets sont identiques sur chaque nœud de calcul et doivent être visibles depuis chaque nœud.
  2. Chaque nœud écrit des points de contrôle, et l'union doit survivre. Avec le partitionnement FSDP ou DeepSpeed, chaque nœud écrit sa propre tranche ; avec DDP, les nœuds écrivent de manière redondante. Dans les deux cas, le système de fichiers subit des pics d'écritures importantes toutes les quelques minutes à quelques heures.

Ces modes d'accès sont opposés. L'accès aux données est continu, séquentiel, axé sur la lecture et tolérant à la latence. L'accès aux points de contrôle est irrégulier, porte sur de gros blocs, est axé sur l'écriture et inclut des blocs d'entraînement. Un système de stockage performant dans un domaine est souvent médiocre dans l'autre.

De plus, les ensembles de données d'apprentissage automatique modernes font une troisième chose : tempêtes de métadonnéesUn ensemble de données de 50 millions d'images JPEG de 4 à 12 Ko représente, du point de vue du système de fichiers, 50 millions de cycles d'ouverture/détection/lecture/fermeture. C'est le serveur de métadonnées, et non le chemin d'accès aux données, qui est le premier à tomber en panne. C'est pourquoi l'argument « nous avons suffisamment de bande passante » est insuffisant.

Charge de travail Patron de Couture Ce dont il a besoin
Mélanger/lire l'ensemble de données Lectures séquentielles soutenues, à l'échelle du téraoctet Bande passante de lecture agrégée
Ensemble de données de petits fichiers Métadonnées aléatoires + lectures de petits fichiers Métadonnées IOPS, faible latence d'opération
écriture du point de contrôle Écritures massives en rafales, tous les nœuds simultanément. Bande passante d'écriture en rafale, sans tête de ligne
Chargement du modèle d'inférence Lecture unique de grande taille au démarrage Tolérant envers tout ce qui est raisonnable

NFS — le système par défaut, et il dure plus longtemps que vous ne le pensez

NFS (NFSv3 ou v4) est la solution la plus simple. Toutes les distributions Linux l'intègrent, tous les planificateurs de tâches le prennent en charge, et un « nœud de stockage » est simplement un serveur Linux doté d'une grande capacité de stockage. /etc/exports ligne et une carte réseau rapide.

Ce qu'un serveur NFS bien conçu vous apporte :

  • Un seul espace de noms monté de manière identique sur chaque nœud de calcul.
  • Débit de lecture séquentielle correct, notamment avec nconnect sur les noyaux modernes (multiplexage d'un montage sur plusieurs connexions TCP — la limite du flux unique a disparu depuis des années).
  • Opérationnellement, c'est ennuyeux. Les pannes sont bien comprises, les procédures de récupération sont décrites dans tous les manuels d'administration système jamais écrits.

Ce à quoi vous renoncez :

  • Un serveur, un goulot d'étranglement. Le débit agrégé du cluster est limité à la capacité de chaque machine.
  • Verrouillage et sérialisation des métadonnées. Les charges de travail liées aux petits fichiers atteignent les limites de métadonnées avant les limites de bande passante.
  • Pas de mise à l'échelle en douceur. Lorsque la première boîte est pleine, vous en créez une seconde avec un point de montage différent, et vos scripts en prennent connaissance.

La mauvaise réputation dont souffre NFS dans le domaine du calcul haute performance (HPC) est principalement due à la limitation à une seule connexion et aux difficultés de gestion des métadonnées pour les petits fichiers. Pour des jeux de données d'entraînement de 100 Go à 1-2 To sur 4 à 8 nœuds GPU, un serveur NFS correctement configuré est parfaitement adapté. Nous avons vu des clients effectuer des ajustements fins de Qwen2.5-VL sur des jeux de données stockés sur NFS sans rencontrer de difficultés.

NFS commence à souffrir lorsque :

  • Les ensembles de données dépassent environ 2 To et les brassages provoquent une saturation du cache sur le serveur.
  • Plus de 8 à 12 nœuds de calcul sollicitent le même support sous charge.
  • Des dizaines de millions de petits fichiers constituent la majeure partie de la charge de travail.
  • La taille des points de contrôle par rang dépasse 50 à 100 Go écrits simultanément.

En deçà de ces quatre seuils, NFS est presque certainement la bonne solution et un système de fichiers parallèle serait surdimensionné.

BeeGFS — le milieu pratique

BeeGFS est le système de fichiers parallèle que l'on déploie réellement lorsque NFS ne suffit plus. Il répartit les données sur plusieurs systèmes de fichiers parallèles. cibles de stockage (disques sur plusieurs serveurs) et cibles de métadonnées (Serveurs NVMe distincts). Les clients voient un seul espace de noms ; les lectures et les écritures sont réparties en bandes sur les cibles de stockage en parallèle.

Pourquoi on le retrouve dans des grappes de taille moyenne :

  • L'installation prend des jours, pas des semaines. Un ingénieur Linux compétent peut mettre en place une installation à deux nœuds de stockage et un MDS en un après-midi. Lustre n'est pas dans cette catégorie.
  • La bande passante agrégée évolue linéairement avec des cibles de stockage. Trois nœuds sur 100 GbE offrent un débit de lecture près de 3 fois supérieur à celui d'un seul nœud.
  • RDMA natif sur InfiniBand ou RoCE — évite la surcharge TCP/IP.
  • Logiciel libre, sans piège des licences par téraoctet. L'assistance commerciale de ThinkParQ est optionnelle.

Ce pour quoi il est honnêtement moins bon :

  • Métadonnées pour les charges de travail comportant un très grand nombre de petits fichiers. Un seul MDS devient le facteur limitant lorsque les fichiers de moins de 4 Ko sont prédominants. Il est possible d'ajouter des cibles de métadonnées, mais l'architecture n'est pas aussi performante que celle de Lustre DNE.
  • Pas de hiérarchisation intégrée. Gérez vous-même le chaud et le froid.
  • HA est un ajout, pas une fonctionnalité native. La mise en miroir fonctionne, mais elle n'est pas aussi transparente que le basculement de Lustre.

Point idéal : 4 à 32 nœuds d'entraînement, 10 à 100 To de données, fichiers de 1 Mo à 1 Go. Là où la plupart des constructions Kentino multi-nœuds sont implantées.

Déploiement BeeGFS de base pour un cluster de 4 nœuds de classe Kentino :

Composant Spec
Nœud de stockage 1 2U, EPYC 24 cœurs, 256 Go de RAM, 12 × 7.68 To NVMe, 2 × 100 GbE
Nœud de stockage 2 Identique
Nœud de métadonnées 1U, processeur EPYC 16 cœurs, 192 Go de RAM, 2 disques NVMe de 3.84 To (RAID-1), 2 ports Ethernet 100 GbE
Réseau Commutateur feuille-épine ou commutateur unique 100 GbE (compatible RoCE)
ANNONCEURS 4 nœuds d'entraînement K-AI, chacun doté d'une interface 100 GbE.

Le débit de lecture agrégé soutenu vers les quatre modules d'entraînement se situe généralement entre 30 et 60 Go/s, suffisant pour alimenter 32 GPU lors de la plupart des entraînements de vision et de modélisation linéaire. Ce débit cesse d'augmenter lorsque le serveur de métadonnées est saturé ; il est alors nécessaire d'ajouter une seconde cible de métadonnées ou d'envisager l'utilisation de Lustre.

Lustre — référence absolue, complexité réelle

Lustre gère la couche de stockage de la quasi-totalité des 500 supercalculateurs les plus puissants nécessitant POSIX, avec une capacité de stockage de plusieurs centaines de pétaoctets et un débit agrégé de plusieurs téraoctets par seconde. Son architecture repose sur trois rôles : MGS/MDS (gestion et métadonnées), OSS (serveurs de stockage objet hébergeant les OST) et les clients. Ces derniers communiquent avec le MDS pour les opérations sur les espaces de noms, puis directement avec l’OSS contenant les données ; le chemin d’accès aux données contourne ainsi le serveur de métadonnées. Cette séparation explique la capacité de Lustre à évoluer, et DNE (Distributed Namespace) permet également une mise à l’échelle horizontale des métadonnées.

Le coût est opérationnel : courbe d’apprentissage plus abrupte que pour BeeGFS, exigences strictes en matière de noyau/pilote, des dizaines de paramètres de réglage (les performances initiales ne correspondent généralement pas aux capacités du matériel) et procédures de récupération qui nécessitent un ingénieur de stockage compétent.

Le seuil à partir duquel Lustre prend tout son sens se situe approximativement entre 16 et 32 ​​nœuds d'entraînement ou ensembles de données de classe PB. En dessous de ce seuil, BeeGFS sature le réseau bien avant que les avantages architecturaux de Lustre ne deviennent significatifs. La plupart des solutions Kentino n'atteignent pas ce seuil ; nous pouvons déployer un cluster Lustre sur demande, mais nous vous précisons d'emblée que BeeGFS, associé à un MDS performant, vous permet d'atteindre 80 % du résultat avec seulement 20 % des difficultés opérationnelles.

Stockage d'objets — MinIO et Ceph pour les lacs de données d'apprentissage automatique

Les systèmes de fichiers parallèles décrits ci-dessus sont corrects lorsque le framework attend des fichiers. Or, une part croissante des pipelines de ML modernes ne fonctionnent pas ainsi : les jeux de données résident sous forme d’objets S3, le chargeur de données les récupère via HTTP et le système de fichiers local sert de répertoire de travail temporaire.

MinIO Il s'agit d'un système de stockage d'objets dédié et compatible S3. Le mode distribué fonctionne sur 4 à 32 nœuds et plus avec codage d'effacement. Open source, il est plus simple à utiliser que n'importe quel système de fichiers parallèle et compatible avec les chargeurs de données modernes (PyTorch avec fsspec/s3fs, WebDataset, NVIDIA DALI) le lisez directement.

Céph Ceph offre une plus grande flexibilité : stockage bloc (RBD), fichier (CephFS) et objet (RGW) sur la même couche RADOS. Il est idéal lorsqu'un seul système de stockage est nécessaire pour plusieurs charges de travail (machines virtuelles, partages de fichiers, objets de machine learning). En revanche, sa simplicité d'utilisation est moindre : Ceph est un système qui exige un engagement, avec sa propre procédure de surveillance, d'optimisation et d'astreinte.

Ce que le stockage objet offre au ML : une capacité économique (les disques durs haute densité avec codage d'effacement offrent des coûts par téraoctet inégalés par la mémoire flash), une mise à l'échelle horizontale simple, un partitionnement par conception (absence de goulot d'étranglement lié aux métadonnées) et une compatibilité optimale avec les chargeurs de données basés sur le partitionnement. Ce qu'il présente en revanche : une latence par opération de l'ordre de la dizaine de millisecondes (et non de la microseconde), l'absence de prise en charge directe de POSIX (il faut réécrire le chargeur ou accepter une pénalité FUSE) et l'impossibilité d'écrire directement sur place (les objets sont immuables — idéal pour les points de contrôle, problématique pour toute modification).

L'architecture qui fonctionne en pratique : Le stockage d'objets comme lac de données durable, volumineux et économique ; un système de fichiers parallèle ou NFS comme ensemble de travail rapide préparé pour l'exécution en cours. L'ensemble de données est stocké sur MinIO. Au démarrage, une tâche place les fragments pertinents sur BeeGFS ou sur un disque temporaire NVMe local. Les points de contrôle finaux sont renvoyés sur MinIO pour archivage.

WekaIO et VAST — le niveau entreprise (en bref)

WekaIO et VAST Data constituent la solution idéale pour les entreprises, avec des métadonnées extrêmement légères, une bande passante agrégée très élevée, une compatibilité native S3 et POSIX, une hiérarchisation intégrée et des chemins d'accès directs aux GPU. Ces solutions sont parfaitement adaptées aux clusters de plus de 100 GPU où le stockage doit suivre le rythme des dépenses liées aux GPU. Elles ne conviennent pas aux serveurs à 4 ou 8 GPU, ni aux clusters de quatre serveurs de ce type : le coût du stockage deviendrait alors le facteur prépondérant. Leur mention ici témoigne de leur pertinence par souci de transparence quant à leur positionnement haut de gamme, et non comme une recommandation pour le public cible de cette série d'articles.

Modèles d'accès aux ensembles de données et leur importance

Deux modèles dominent l'entraînement en apprentissage automatique. Modèle A — grands fragments : Les jeux de données sont pré-compressés dans des archives WebDataset, au format Parquet ou LMDB, avec une taille de 100 Mo à 10 Go par partition, lus séquentiellement et réorganisés en interne. Tous les systèmes de stockage sont performants pour cela. Modèle B — de nombreux petits fichiers : Des millions de fichiers JPEG/PNG/JSON, un par échantillon, saturent le chemin des métadonnées. Cela met à rude épreuve NFS, nuit aux performances de BeeGFS à grande échelle et explique l'existence de Weka et VAST.

La décision ayant le plus grand impact sur le stockage des données de formation consiste à déplacer le modèle B vers le modèle A. Si vos données sont composées de petits fichiers, regroupez-les en fragments avant l'entraînement. Cela nécessite une étape de prétraitement, mais permet d'utiliser n'importe quel système de stockage. Nous avons constaté des gains de vitesse de 3 à 5 fois sur les pipelines, sans modification du matériel de stockage, grâce à ce simple regroupement.

Si le reconditionnement est impossible (les données étant constamment modifiées, le framework exige impérativement des fichiers par échantillon), dimensionnez le stockage en fonction des IOPS des métadonnées, et non de la bande passante. Cela vous oriente vers BeeGFS avec plusieurs cibles MDS, Weka/VAST ou Lustre avec DNE.

Stratégie de points de contrôle — écrire vite, écrire plus tard, écrire moins

L'écriture par points de contrôle représente le pire scénario : chaque rang écrit simultanément, les écritures sont volumineuses et les blocs d'entraînement sont stockés jusqu'à leur validation. Un point de contrôle synchrone naïf sur un modèle à 100 milliards de paramètres peut bloquer l'entraînement pendant des dizaines de minutes.

La meilleure pratique actuelle consiste en une approche en trois étapes, native dans PyTorch. torch.distributed.checkpoint (DCP), NVIDIA NeMo et la plupart des frameworks modernes :

  1. Chaque rang écrit son fragment sur le disque temporaire NVMe local. La bande passante d'écriture totale du cluster correspond à la somme des débits NVMe par nœud (5 à 50 Go/s chacun). L'entraînement se débloque en quelques secondes.
  2. Un processus d'arrière-plan asynchrone effectue une copie vers un stockage partagé. L'entraînement a repris.
  3. Les points de contrôle plus anciens sont supprimés ou déplacés vers le stockage d'objets selon un calendrier prédéfini. Conservez les 2 ou 3 derniers sur un stockage rapide, le reste sur MinIO/Ceph.

L'implication: Le stockage partagé n'a pas besoin d'absorber chaque point de contrôle à pleine vitesse. Il est nécessaire d'ingérer la copie asynchrone sans que le système ne prenne du retard. Pour un modèle de 70 octets effectuant un point de contrôle toutes les 30 minutes, un débit d'écriture soutenu de quelques Go/s est suffisant ; il est largement à la portée d'un serveur BeeGFS performant ou d'un bon serveur NFS.

L'erreur à éviter : points de contrôle synchrones et non partitionnés écrits directement sur NFS. C'était normal en 2022. Ce n'est plus le cas. Si votre pipeline fonctionne ainsi, corriger le code du point de contrôle est plus avantageux que de mettre à niveau le stockage.

La question de la liaison montante du cluster

Le trafic de stockage partage-t-il le même réseau que l'entraînement, ou bénéficie-t-il d'un réseau séparé ?

Tissu partagé
Une seule connexion 100/200 GbE ou IB prend en charge à la fois la réduction de bande passante et le stockage. Plus économique et plus simple. Risque : les pics de trafic lors des points de contrôle peuvent perturber le protocole NCCL et l’entraînement au blocage.
Tissu fendu
Deux cartes réseau par nœud : une pour le calcul (IB), l’autre pour le stockage (Ethernet). Domaines de congestion indépendants. Environ deux fois plus d’équipements réseau.

L'architecture partagée convient aux clusters de 4 à 8 nœuds avec point de contrôle asynchrone ; l'architecture divisée est justifiée au-delà de 8 nœuds ou en cas d'E/S synchrones importantes.

Pour les clusters de classe Kentino (4 à 8 nœuds), une infrastructure partagée convient parfaitement lorsque la sauvegarde asynchrone est utilisée et que la charge de stockage est principalement constituée de lectures : les lectures soutenues coexistent avec les opérations collectives NCCL sans problème majeur. Une infrastructure divisée se justifie pour les entraînements LLM de grande envergure avec FSDP à un taux de TP/PP élevé, un trafic de stockage synchrone important, ou lorsque le budget le permet. En pratique, la configuration par défaut est un réseau 100 GbE partagé jusqu’à 8 nœuds avec un VLAN de stockage pour une isolation souple.

Recommandations honnêtes par échelle

Scale Ensemble de données Niveau de stockage Remarques
Noeud 1 Toutes NVMe local Évitez complètement le stockage partagé.
2 à 3 nœuds d'entraînement < 1 To NFS sur un nœud de stockage puissant nconnect, une quantité généreuse de RAM pour le cache de pages.
4 à 8 nœuds d'entraînement 1 à 10 To NFS, ou premier déploiement BeeGFS BeeGFS si l'ensemble de données contient beaucoup de petits fichiers.
4 à 16 nœuds d'entraînement 10 à 100 To BeeGFS, 2 à 3 cibles de stockage, MDS dédié Point idéal. Ajoutez MinIO pour l'archivage à froid.
16 à 32+ nœuds d'entraînement 100 TB–1 PB BeeGFS a poussé fort, ou Lustre Point de décision pour Lustre.
Plus de 32 nœuds, à l'échelle du pétaoctet, 24h/24 et 7j/7 PB+ Lustre, ou Weka/VAST si le budget le permet. Au-delà de la construction typique de Kentino.
Grand lac de données, formation épisodique PB+ froid MinIO/Ceph, passage au niveau rapide par tâche « Beaucoup de données, formation occasionnelle. »

La plupart des clients de Kentino se situent dans les rangées deux et trois. Nous réalisons les autres sur demande, mais nous vous indiquerons s'il s'agit d'une configuration surdimensionnée.

Qu'est-ce qui casse ?

Modes de défaillance observés, classés par fréquence d'apparition :

  • Pénurie de métadonnées en cas de faible charge de fichiers. Symptôme : GPU à 30–50 %, réseau inactif, processeur de stockage inactif, à chaque open() Lent. Solution : recompresser en fragments ou augmenter la taille des cibles MDS.
  • Les points de contrôle synchrones bloquent la formation. Correction : points de contrôle asynchrones fragmentés (PyTorch DCP ou NeMo).
  • Un disque lent qui fait dérailler le cluster. Un SSD défaillant ne tombe pas en panne brutalement ; il ralentit simplement. Solution : surveiller la latence de chaque périphérique et déclencher une alarme lorsque celle-ci dépasse le double de la valeur de référence.
  • Surcharge du cache de pages sur le nœud de stockage. L'ensemble de données ne tient pas dans la RAM ; chaque époque écrase la précédente. Solution : augmenter la RAM.
  • nconnect non activé sur les clients NFS. Les limites NFS par défaut pour un seul flux sont bien inférieures au débit de la ligne NIC. nconnect=8 or =16 offre un débit 4 à 8 fois supérieur sur le même matériel.
  • MinIO à grande échelle sans réglage EC. Les paramètres par défaut privilégient la durabilité à la latence ; la latence des petits objets s'en trouve affectée. Ne les acceptez pas aveuglément.

Aucun de ces exemples n'est exotique. Tous sont prévisibles une fois qu'on les a vus.

Que faire ensuite

Si vous spécifiez le stockage pour un cluster d'entraînement nouveau ou en expansion, répondez à ces questions avant de signer pour le matériel :

  1. Forme de l'ensemble de données : grands fragments ou nombreux petits fichiers ? Le principal facteur déterminant le choix du système de stockage adapté.
  2. Ensemble de travail actif, et non taille du lac de données. Le budget de stockage est alloué à l'ensemble de travail ; le système de stockage du lac utilise un stockage d'objets moins cher, mais plus lent.
  3. Cadence des points de contrôle, taille, tolérance aux blocages. La taille indique la capacité d'écriture en rafale et vous informe si les points de contrôle asynchrones fragmentés sont obligatoires (généralement au-dessus de ~13 octets de paramètres, oui).
  4. Formation des nœuds aujourd'hui et projection réaliste sur 12 mois. Si vous prévoyez d'utiliser 4 nœuds pendant un an, configurez votre infrastructure pour 4 nœuds. N'achetez pas Lustre à l'avance.
  5. Rangement sur le tissu d'entraînement ou séparé ? Décidez avant le câblage, pas après.
  6. Plan d'archivage à froid. Modèles, versions des jeux de données, artefacts d'exécution terminés : ces données doivent être stockées à moindre coût. MinIO ou Ceph constituent généralement la solution.

Dans un cluster d'IA, le stockage, plus que tout autre composant, incite à anticiper les problèmes, car le coût d'une erreur de conception se répercute à chaque entraînement, et ce, pendant toute la durée de vie du système. L'objectif véritable n'est pas d'acquérir le stockage le plus rapide possible, mais plutôt le stockage le plus simple qui ne bride pas les GPU existants. Pour la plupart des architectures de l'envergure d'un Kentino, cette solution est bien moins sophistiquée que ne le laissent entendre les arguments marketing des fournisseurs.

Articles connexes : K01 (nœud unique vs nœuds multiples), K02 (mécanismes de formation distribuée), K03 (groupes d'inférence), N08 (RDMA + liaison montante de cluster), W06 (niveaux de stockage au sein d'un seul serveur).


Ceci fait partie du Kentino Wiki, une série de référence sur l'intelligence artificielle, la robotique et les systèmes qui les connectent. Commentaires et corrections bienvenus. info@kentino.com.