Pièges de formation Spark
Le chip GB10 de DGX Spark (Grace Blackwell, SM121, 128 GB de mémoire unifiée, aarch64) présente dix modes de défaillance récurrents touchant au lancement, à la mémoire, aux thermiques, à la bande passante et à la précision. Chacun est numéroté G1–G10 pour être vérifiable par numéro — la numérotation est structurante pour les outils qui exécutent ces vérifications. Lisez ceci avant une longue exécution, pas après six heures.
Quand utiliser cette compétence
- Une exécution de formation échoue au démarrage, avec une erreur d'import ou un segfault qui ne pointe pas vers la vraie cause.
- Une exécution OOM alors que
nvidia-smiaffiche encore de la marge disponible. - Le débit se dégrade en cours d'exécution qui avait bien commencé.
- Avant tout travail multi-heures ou multi-epochs sur GB10.
- Avant de câbler deux Sparks ensemble, avant de choisir une stratégie de parallélisme.
- Avant de choisir entre FP8 et NVFP4 pour une exécution hébergée sur Spark.
Référence rapide des problèmes courants
| # | Symptôme | Solution |
|---|---|---|
| G1 | symbole indéfini / segfault | wheel cu130 ou conteneur |
| G2 | mauvais backend flash-attn utilisé | skip pip build; monkeypatch sur NGC |
| G3 | OOM malgré marge disponible | drop page cache |
| G4 | baisse débit / reboot | attendre ~100W cap soutenu |
| G5 | étape memory-bound lente | budget 180–192 GB/s |
| G6 | cache évincé en cours d'exécution | un serveur GPU à la fois |
| G7 | NVFP4 plus lent que FP8 | rester FP8 sauf sm_121a |
| G8 | playbook échoue complètement | vérifier problèmes upstream |
| G9 | env casse après install | utiliser un conteneur |
| G10 | TP 2-Spark se bloque | DDP/FSDP uniquement, jamais TP |
Les dix pièges
G1 : Incompatibilité ABI CUDA 12/13
- SYMPTÔME :
ImportError: undefined symbolnommant une fonction CUDA, ou segfault au premier appel.cuda(). - CAUSE : la plupart des wheels PyPI lient
libcudart.so.12; Spark embarque CUDA 13. pip ne vérifier jamais l'ABI CUDA, donc cela n'apparaît qu'à l'import ou au premier lancement de kernel. - VÉRIFICATION :
references/gotcha-checks.mdG1 — le tag de build CUDA du wheel. - SOLUTION : réinstallez depuis
download.pytorch.org/whl/cu130ou utilisez un conteneur compatible.
G2 : flash-attn — Skip pip Build, Surveiller l'auto-détection Unsloth
- SYMPTÔME :
pip install flash-attnéchoue/se bloque toujours. Unsloth peut aussi entraîner silencieusement flash-attn sur un SDPA explicitement demandé. - CAUSE : pas de wheel aarch64/sm_121 pour pip brut — mais les conteneurs NGC livrent un flash-attn SM121 fonctionnant, et Unsloth l'auto-préfère, supprimant
attn_implementation="sdpa". - VÉRIFICATION :
references/gotcha-checks.mdG2 — flash-attn est-il déjà présent et fonctionnant. - SOLUTION : pip brut — skip flash-attn, utilisez SDPA (inchangé). Sur NGC — le seul override fiable est le monkeypatch dans
references/gotcha-checks.mdG2.
G3 : OOM UMA sous 128 GB
- SYMPTÔME : OOM lors du chargement/entraînement du modèle tandis que
nvidia-smirapporte toujours de la mémoire libre sous le cap 128 GB — ou, sur certaines configurations,[N/A]purement et simplement au lieu d'un nombre. - CAUSE : mmap et l'allocateur CUDA double-comptent les pages lors du chargement safetensors ; QLoRA peut OOM plus tôt que bf16 puisque la dédéquantification ajoute des allocations transitoires.
- VÉRIFICATION :
references/gotcha-checks.mdG3 — lisezfree -get/proc/meminfo, pasnvidia-smi. - SOLUTION : videz le cache de pages avec
sync; echo 3 > /proc/sys/vm/drop_caches— nécessite root, une réinitialisation entre exécutions, pas une étape en cours d'entraînement.
G4 : Limitation thermique
- SYMPTÔME : le débit baisse en cours d'exécution multi-heures, ou le serveur redémarre spontanément sous charge soutenue.
- CAUSE : la consommation électrique soutenue plafonne autour de 100W face à la figure nominale de 240W ; les longues exécutions heurtent ce plafond et limiteront ou, parfois, redémarreront.
- VÉRIFICATION :
references/gotcha-checks.mdG4 — échantillonneznvidia-smi --query-gpu=temperature.gpu,power.draw. - SOLUTION : si la puissance plafonne sous 240W tandis que la température grimpe, traitez la limitation comme cause ; améliorez le refroidissement ou limitez la durée d'exécution.
G5 : Plafond de bande passante
- SYMPTÔME : les charges memory-bound, les boucles RL heavy-decode notamment, plafonnent bien en dessous du débit attendu.
- CAUSE : 273 GB/s est un plafond spec, pas soutenu ; la bande passante mesurée tourne 180–192 GB/s.
- VÉRIFICATION :
references/gotcha-checks.mdG5 — temps d'étape observé vs plage mesurée, pas spec. - SOLUTION : budgétez la bande passante 180–192 GB/s ; révisez un plan construit sur la figure 273 GB/s.
G6 : Contention de ressources UMA globale
- SYMPTÔME : le KV cache/poids d'un processus se font évincer en cours d'exécution silencieusement, pas d'OOM dans ses propres logs.
- CAUSE : la mémoire unifiée est un pool global ; un processus sans cap ou près de capacité entre en compétition avec tout autre et peut l'évincer. Une petite charge bornée ne le fait pas — un LoRA <4 GB coexiste bien aux côtés d'une vLLM cappée à
gpu-memory-utilization<=0.5. - VÉRIFICATION :
references/gotcha-checks.mdG6 — autres processus résidents GPU et s'ils sont cappés. - SOLUTION : la règle un-gros-job s'applique aux charges sans cap ou près de capacité — cappez ou arrêtez d'abord les serveurs sans rapport. Une petite charge cappée ne doit pas s'arrêter.
G7 : NVFP4 plus lent que FP8 sur SM121
- SYMPTÔME : basculer une charge inference de FP8 à NVFP4 sur Spark la ralentit, ne l'accélère pas.
- CAUSE : SM121 manque
cvt.e2m1x2sauf si les kernels ciblentsm_121a; NVFP4 tourne ~32% plus lentement sans cela. - VÉRIFICATION :
references/gotcha-checks.mdG7 — les rapports de capacité montrent(12, 1); le build cible-t-ilsm_121a? - SOLUTION : restez sur FP8 sauf si le build cible
sm_121a.
G8 : Playbooks officiels périmés
- SYMPTÔME : suivre un playbook DGX Spark officiel échoue toujours, sans configuration locale erronée l'expliquant.
- CAUSE : les playbooks officiels ont livré cassés avant ; la pile évolue plus vite que les docs.
- VÉRIFICATION :
references/gotcha-checks.mdG8 — les problèmes récents du repo playbook. - SOLUTION : vérifiez
github.com/NVIDIA/dgx-spark-playbooksissues avant de faire confiance à une recette pour une exécution coûteuse.
G9 : Conteneur d'abord, pas pip brut
- SYMPTÔME : un environnement pip brut qui fonctionnait hier casse après une
pip installsans rapport, ou deux environnements "identiques" se comportent différemment. - CAUSE : pip brut laisse Triton, xformers et transformers dériver indépendamment ; rien ne les épingle à la cible SM121 de GB10.
- VÉRIFICATION :
references/gotcha-checks.mdG9 — conteneur ou pip brut ? - SOLUTION : préférez un conteneur NGC (voir
spark-environment-setuppour guidance de tag) ou le conteneur Unsloth. Si pip brut est inévitable, suivez l'ordre d'install NVIDIA, incluant--no-depssur Unsloth.
G10 : Dual-Spark est DDP/FSDP uniquement
- SYMPTÔME : un lancement tensor-parallel sur deux Sparks se bloque, tourne beaucoup plus lent qu'un single-Spark, ou erreurs.
- CAUSE : ConnectX-7 est assez rapide pour la sync gradient/paramètre (DDP, FSDP) mais trop fin pour le trafic fin-grained du TP.
- VÉRIFICATION :
references/gotcha-checks.mdG10 — la stratégie de parallélisme configurée. - SOLUTION : sur setup deux-Spark, choisissez DDP ou FSDP, jamais tensor parallelism — le TP est single-node uniquement ici.
Triage rapide
Les vérifications les moins chères à exécuter avant toute chose :
python3 -c "import torch; print(torch.version.cuda)" # attendre 13.x (G1); les builds NGC n'ont pas le tag +cu130 — ce n'est pas une défaillance
import torch; print(torch.cuda.get_device_capability()) # attendre (12, 1) (G7)
{ [ -f /.dockerenv -o -f /run/.containerenv ] || grep -qE 'docker|containerd' /proc/1/cgroup; } 2>/dev/null && echo container || echo unknown # G9
assets/preflight.sh exécute G1, G3, G4, G7, G9 et produit une ligne de sortie par piège dans un format fixe : le G-number d'abord, puis PASS/FAIL/WARN où automatisable, SKIP si indisponible, ou INFO: pour une lecture brute (G3, G4). Commandes complètes : references/gotcha-checks.md. Voir aussi spark-environment-setup pour l'environnement assumé fonctionnant.