Dotika MLOps · Bonus — GPUBonus — GPU
▶ Slides▶ Slides ← Sommaire← Contents
Bonus · 2 h · théorie 0h40 · lab 1h20 · optionnelBonus · 2 h · theory 0h40 · lab 1h20 · optional

Pour aller plus loin :
le GPU
Going further:
the GPU

L'usine à calcul — comprendre quand un GPU sert, quand il ne sert à rien, et comment le brancher à vos conteneurs avec --gpus. The compute factory — understanding when a GPU helps, when it is useless, and how to plug it into your containers with --gpus.

Acte 1 · l'usine et l'artisan · théorie 0h40Act 1 · the factory and the craftsman · theory 0h40

Quelques artisans, ou dix mille ouvriersA few craftsmen, or ten thousand workers

Le CPU, c'est quelques artisans géniaux : peu de cœurs, très rapides, capables de tout faire. Le GPU, c'est une usine de milliers d'ouvriers simples : le même geste, en même temps, sur des données différentes. Toute la question du bonus tient là : votre calcul est-il un travail d'artisan ou un travail d'usine ? The CPU is a few brilliant craftsmen: few cores, very fast, able to do anything. The GPU is a factory of thousands of simple workers: the same move, at the same time, on different data. The whole bonus fits in one question: is your computation a craftsman's job or a factory job?

8–16
cœurs CPU — polyvalents, malins, capables d'improviser à chaque instructionCPU cores — versatile, clever, able to improvise on every instruction
10 000+
cœurs GPU — spécialisés, synchrones, imbattables pour répéter le même gesteGPU cores — specialized, synchronized, unbeatable at repeating the same move
~20×
plus rapide sur les multiplications de matrices — le cœur du deep learningfaster on matrix multiplications — the heart of deep learning
CUDA — le langage de l'usineCUDA — the factory's language
Le dialecte NVIDIA pour programmer le GPU. Vous ne l'écrirez sans doute jamais : PyTorch et TensorFlow le parlent pour vous.NVIDIA's dialect for programming the GPU. You will probably never write it: PyTorch and TensorFlow speak it for you.
cuDNN — les gestes optimiséscuDNN — the optimized moves
Les opérations de deep learning pré-réglées à la perfection : convolutions, attention… Des années d'optimisation, gratuites.Deep learning operations tuned to perfection: convolutions, attention… Years of optimization, for free.
Le driver — le contremaîtreThe driver — the foreman
Le seul qui parle vraiment à la carte. Il vit sur la machine hôte — et uniquement là. C'est la clé des conteneurs GPU.The only one that truly talks to the card. It lives on the host machine — and only there. It is the key to GPU containers.
L'honnêteté d'ingénieurEngineering honesty

Quand le GPU sert — et quand il ne sert à rienWhen the GPU helps — and when it is useless

Notre régression logistique s'entraîne en 2 secondes sur CPU : un GPU n'y changerait rien, sauf la facture. Réclamer une usine pour visser une étagère n'impressionne personne. Mais quatre situations la rendent indispensable : Our logistic regression trains in 2 seconds on CPU: a GPU would change nothing, except the bill. Demanding a factory to screw in a shelf impresses nobody. But four situations make it essential:

CAS 1CASE 1
Deep learning
Des millions de poids à ajuster : des jours de CPU deviennent des heures de GPU. Là, l'usine se rentabilise.Millions of weights to adjust: days of CPU become hours of GPU. There, the factory pays for itself.
CAS 2CASE 2
Images & visionImages & vision
Des convolutions sur des millions de pixels — le même geste partout. Le travail d'usine par définition.Convolutions over millions of pixels — the same move everywhere. A factory job by definition.
CAS 3CASE 3
LLM
Des dizaines de milliards de paramètres, à l'entraînement comme à l'inférence. Sans GPU, chaque réponse prendrait des minutes.Tens of billions of parameters, for training and inference alike. Without GPUs, every answer would take minutes.
CAS 4CASE 4
Gros volumes, réentraînements fréquentsBig volumes, frequent retraining
Quand l'entraînement se compte en heures et revient chaque semaine — le continuous training du bloc 8 — chaque accélération paie.When training takes hours and comes back weekly — block 8's continuous training — every speed-up pays off.
Le message honnêteThe honest message

Le GPU est un outil, pas un trophée. Mesurez avant de payer : un chrono CPU, un chrono GPU, et la décision se prend en euros — comme toutes les décisions de la semaine. The GPU is a tool, not a trophy. Measure before you pay: one CPU timer, one GPU timer, and the decision is made in euros — like every decision this week.

Acte 2 · le GPU en conteneurAct 2 · the GPU in a container

Le conteneur ne voit pas la carte — construisons le pontThe container can't see the card — let's build the bridge

Par défaut, Docker isole — c'est son métier. Le GPU est un périphérique de l'hôte : sans pont explicite, torch.cuda.is_available() répond False dans le conteneur. Le pont officiel s'appelle le NVIDIA Container Toolkit. By default, Docker isolates — that's its job. The GPU is a host device: without an explicit bridge, torch.cuda.is_available() answers False inside the container. The official bridge is the NVIDIA Container Toolkit.

LE PONTTHE BRIDGE
NVIDIA Container Toolkit
Il monte le driver de l'hôte dans le conteneur. Installé une fois par machine — jamais dans l'image.It mounts the host's driver into the container. Installed once per machine — never in the image.
LE GESTETHE MOVE
docker run --gpus all
Un drapeau, et l'usine s'ouvre. --gpus '"device=0"' choisit une carte précise — le réflexe sur machine partagée.One flag, and the factory opens. --gpus '"device=0"' picks one specific card — the reflex on a shared machine.
LE TABLEAU DE BORDTHE DASHBOARD
nvidia-smi
Trois chiffres : utilisation (l'usine tourne-t-elle ?), mémoire (le modèle tient-il ?), température. À lire avant d'accuser le code.Three numbers: utilization (is the factory running?), memory (does the model fit?), temperature. Read it before blaming the code.
LA BASETHE BASE
nvidia/cuda:12.4.1-runtime-ubuntu22.04
~2-3 Go, de quoi exécuter. La variante -devel (~7-8 Go) n'est utile que pour compiler du CUDA — presque jamais vous.~2-3 GB, enough to run. The -devel variant (~7-8 GB) is only useful for compiling CUDA — almost never you.
LE PIÈGETHE TRAP
Des images de plusieurs GoMulti-GB images
Base CUDA + PyTorch GPU ≈ 7 Go : pulls interminables, registry qui déborde. Les réflexes Docker du bloc 4 valent triple ici.CUDA base + GPU PyTorch ≈ 7 GB: endless pulls, overflowing registry. Block 4's Docker reflexes are worth triple here.
LA PILETHE STACK
Votre code ne touche jamais la carteYour code never touches the card
PyTorch → cuDNN → CUDA → driver → GPU. Les versions doivent s'aimer entre voisines — 90 % des pannes viennent de là.PyTorch → cuDNN → CUDA → driver → GPU. Versions must get along with their neighbours — 90% of failures come from there.
Lab · 1h20Lab · 1h20

À vous de jouerYour turn

Deux missions sur la machine GPU partagée. Les durées viennent du plan de cours : Two missions on the shared GPU machine. Durations come straight from the course plan:

0h50
Brancher l'usine — installer le NVIDIA Container Toolkit, lancer un conteneur avec --gpus all, prouver que la carte est visible : nvidia-smi depuis l'intérieur, torch.cuda.is_available() → TruePlug in the factory — install the NVIDIA Container Toolkit, run a container with --gpus all, prove the card is visible: nvidia-smi from the inside, torch.cuda.is_available() → True
pratiquehands-on
0h30
La course, en vrai — image sur base nvidia/cuda:12.4.1-runtime-ubuntu22.04, entraînement chronométré CPU puis GPU sur un petit réseau, et sur la régression logistique de la fraude : un tableau comparatif commitéThe race, for real — image on a nvidia/cuda:12.4.1-runtime-ubuntu22.04 base, timed CPU then GPU training on a small network, and on the fraud project's logistic regression: a comparison table, committed
pratiquehands-on
Definition of done

La capture de nvidia-smi exécuté dans un conteneur, et un tableau de temps CPU vs GPU avec votre conclusion en une phrase honnête. Attendu : ~20× sur le réseau, quasi rien sur la fraude — et c'est exactement le message. The output of nvidia-smi run inside a container, and a CPU vs GPU timing table with your conclusion in one honest sentence. Expected: ~20× on the network, next to nothing on the fraud model — and that is exactly the message.

Pas à pas · en autonomieStep by step · self-paced

Faites-le vous-même, de A à ZDo it yourself, start to finish

Ce guide reprend les deux missions du lab, commande par commande. Préambule honnête : il vous faut une machine Linux (ou Windows + WSL2) avec un GPU NVIDIA et Docker — la machine partagée de la formation, un PC de jeu, ou une instance cloud GPU. Sans carte NVIDIA (Mac inclus), lisez simplement les étapes : le résultat attendu est donné à chaque point de contrôle, et c'est le raisonnement qui compte. Placez-vous dans le dépôt fraud-detection/. This guide replays the lab's two missions, command by command. Honest preamble: you need a Linux machine (or Windows + WSL2) with an NVIDIA GPU and Docker — the training's shared machine, a gaming PC, or a cloud GPU instance. Without an NVIDIA card (Macs included), simply read through the steps: the expected result is given at every checkpoint, and the reasoning is what matters. Work from the fraud-detection/ repo.

Mission 1 — Brancher l'usine (0h50)Mission 1 — Plug in the factory (0h50)

1Vérifier le driver sur l'hôteCheck the driver on the host

Le driver est le contremaître : il vit sur l'hôte, et lui seul parle à la carte. Rien d'autre ne marchera tant que cette commande ne répond pas. The driver is the foreman: it lives on the host, and it alone talks to the card. Nothing else will work until this command answers.

nvidia-smi
Vous devriez voir : le tableau avec le nom de la carte, la version du driver et « CUDA Version: 12.x ». Si « command not found » : installez d'abord le driver NVIDIA de votre distribution.You should see: the table with the card's name, the driver version and "CUDA Version: 12.x". If "command not found": install your distribution's NVIDIA driver first.
2Installer le NVIDIA Container ToolkitInstall the NVIDIA Container Toolkit

Le pont officiel entre Docker et la carte — installé une fois par machine, jamais dans l'image. Ce sont les commandes officielles pour Ubuntu / Debian. The official bridge between Docker and the card — installed once per machine, never inside the image. These are the official commands for Ubuntu / Debian.

curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
  sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
nvidia-ctk --version
Vous devriez voir : l'installation se terminer sans erreur, et nvidia-ctk répondre avec sa version.You should see: the install finish with no error, and nvidia-ctk answer with its version.
3Déclarer le runtime auprès de DockerRegister the runtime with Docker

Le toolkit est installé, mais Docker ne le connaît pas encore : une commande de configuration, un redémarrage du démon, et le drapeau --gpus devient disponible. The toolkit is installed, but Docker does not know it yet: one configuration command, one daemon restart, and the --gpus flag becomes available.

sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
docker info | grep -i runtimes
Vous devriez voir : la ligne Runtimes contenant nvidia aux côtés de runc.You should see: the Runtimes line listing nvidia next to runc.
4Le premier conteneur GPUThe first GPU container

Le moment de vérité : un conteneur CUDA officiel, le drapeau --gpus all, et nvidia-smi exécuté depuis l'intérieur. Sur machine partagée, le réflexe est --gpus '"device=0"' pour ne prendre qu'une carte. The moment of truth: an official CUDA container, the --gpus all flag, and nvidia-smi executed from the inside. On a shared machine, the reflex is --gpus '"device=0"' to claim a single card.

docker run --rm --gpus all nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi
Vous devriez voir : le même tableau nvidia-smi qu'à l'étape 1 — mais imprimé depuis l'intérieur du conteneur. Le pont fonctionne.You should see: the same nvidia-smi table as in step 1 — but printed from inside the container. The bridge works.

Mission 2 — La course, en vrai (0h30)Mission 2 — The race, for real (0h30)

5runtime vs devel : peser avant de choisirruntime vs devel: weigh before you choose

Une phrase suffit : -runtime sait exécuter du CUDA, -devel sait le compiler — et pèse trois fois plus. Sauf besoin explicite de compilation, prenez runtime. Vérifiez-le sur la balance : One sentence is enough: -runtime can run CUDA, -devel can compile it — and weighs three times as much. Unless you explicitly need to compile, pick runtime. Check it on the scale:

docker pull nvidia/cuda:12.4.1-runtime-ubuntu22.04
docker pull nvidia/cuda:12.4.1-devel-ubuntu22.04
docker images nvidia/cuda
Vous devriez voir : -runtime autour de 2-3 Go, -devel autour de 7-8 Go — même CUDA, trois fois le poids.You should see: -runtime around 2-3 GB, -devel around 7-8 GB — same CUDA, three times the weight.
6Écrire le banc d'essai : bench.pyWrite the benchmark: bench.py

Le fichier entier, à la racine du dépôt : une multiplication de matrices 4096 × 4096 chronométrée sur CPU, puis sur GPU si la carte est visible. Le synchronize() est essentiel — sans lui, on chronomètre le lancement du calcul, pas le calcul. The whole file, at the repo root: a 4096 × 4096 matrix multiplication timed on CPU, then on GPU if the card is visible. The synchronize() is essential — without it you time the launch of the computation, not the computation.

"""Time a 4096x4096 matmul on CPU, then on GPU if available."""
import time

import torch

SIZE = 4096
ROUNDS = 10


def bench(device):
    a = torch.randn(SIZE, SIZE, device=device)
    b = torch.randn(SIZE, SIZE, device=device)
    torch.matmul(a, b)  # warmup
    if device == "cuda":
        torch.cuda.synchronize()
    start = time.perf_counter()
    for _ in range(ROUNDS):
        torch.matmul(a, b)
    if device == "cuda":
        torch.cuda.synchronize()
    return (time.perf_counter() - start) / ROUNDS


cpu_time = bench("cpu")
print(f"cpu:  {cpu_time * 1000:.1f} ms per matmul")

if torch.cuda.is_available():
    gpu_time = bench("cuda")
    print(f"cuda: {gpu_time * 1000:.1f} ms per matmul")
    print(f"speedup: x{cpu_time / gpu_time:.1f}")
else:
    print("cuda not available in this container")
Vous devriez voir : le fichier bench.py enregistré à la racine du dépôt — il tournera dans le conteneur à l'étape 7, rien à installer localement.You should see: bench.py saved at the repo root — it will run inside the container in step 7, nothing to install locally.
7La course : sans, puis avec --gpusThe race: without, then with --gpus

Même image, même script, un seul drapeau de différence. Et le rappel honnête : sur la régression logistique de la fraude (2 s de CPU au total), ce gain n'existe pas — aucune matrice géante à paralléliser. Mesurez, puis décidez en euros. Same image, same script, one flag of difference. And the honest reminder: on the fraud project's logistic regression (2 s of CPU in total), this gain does not exist — no giant matrix to parallelize. Measure, then decide in euros.

docker run --rm -v "$PWD":/work -w /work pytorch/pytorch:2.3.1-cuda12.1-cudnn8-runtime python bench.py
docker run --rm --gpus all -v "$PWD":/work -w /work pytorch/pytorch:2.3.1-cuda12.1-cudnn8-runtime python bench.py
Vous devriez voir : sans --gpus, « cuda not available in this container » et un matmul CPU en centaines de ms ; avec --gpus all, un matmul CUDA ~20× plus rapide (speedup: x20 environ, selon la carte).You should see: without --gpus, "cuda not available in this container" and a CPU matmul in hundreds of ms; with --gpus all, a CUDA matmul ~20× faster (speedup: around x20, depending on the card).
Si ça coinceWhen it breaks

« could not select device driver "nvidia" » — le toolkit n'est pas déclaré auprès de Docker : rejouez nvidia-ctk runtime configure --runtime=docker puis systemctl restart docker (étape 3). « CUDA driver version is insufficient » — l'image demande un CUDA plus récent que votre driver : mettez le driver à jour, ou prenez une image CUDA plus ancienne — le driver de l'hôte doit toujours être au niveau du CUDA de l'image. Une image de 8 Go — vous avez tiré -devel : préférez -runtime (l'étape 5 montre l'écart), et les réflexes du bloc 4 valent triple ici. WSL2 — le driver s'installe côté Windows, jamais dans WSL ; nvidia-smi doit répondre dans WSL avant de toucher Docker, et Docker Desktop doit avoir l'intégration WSL2 activée. "could not select device driver "nvidia"" — the toolkit is not registered with Docker: rerun nvidia-ctk runtime configure --runtime=docker then systemctl restart docker (step 3). "CUDA driver version is insufficient" — the image asks for a newer CUDA than your driver: update the driver, or pick an older CUDA image — the host driver must always match the image's CUDA level. An 8 GB image — you pulled -devel: prefer -runtime (step 5 shows the gap), and block 4's reflexes are worth triple here. WSL2 — the driver installs on the Windows side, never inside WSL; nvidia-smi must answer inside WSL before you touch Docker, and Docker Desktop must have WSL2 integration enabled.