CUDA, cuDNN i NVIDIA Container Toolkit: rozsądna ścieżka konfiguracji serwera AI
Mają Państwo świeżo zamontowany w racku serwer z czterema lub ośmioma GPU, Ubuntu 22.04 albo 24.04, przypięty sterownik NVIDIA (zgodnie z L01), a nvidia-smi zwraca sensowne liczby. To dopiero podłoga. Nad nią piętrzy się niewdzięczny stos — CUDA, cuDNN, container toolkit, środowiska uruchomieniowe, obrazy NGC — który większość poradników zbywa machnięciem ręki. Ten artykuł prowadzi od sterownika aż do momentu, w którym docker run --gpus all rozświetla każdą kartę, a kontener vLLM zaczyna serwować tokeny.
Mamy wyrobione zdanie co do tego, którą drogą iść, i uczciwie mówimy, która potrafi ugryźć.
Triada: sterownik / runtime / toolkit
Pod parasolem „CUDA” kryją się trzy rzeczy, które nagminnie się ze sobą myli:
| Komponent | Gdzie żyje | Co robi | Kto to instaluje |
|---|---|---|---|
| Sterownik NVIDIA | Moduł jądra + przestrzeń użytkownika | Rozmawia z GPU. Jest właścicielem urządzenia. Ustawia stan PCIe, moc i zegary. | System / apt / DKMS |
| Runtime CUDA | Biblioteki .so w przestrzeni użytkownika |
Implementuje API CUDA, z którym linkuje się aplikacja. | Pakiet aplikacji lub system |
| Toolkit CUDA |
nvcc, nagłówki, przykłady |
Kompiluje CUDA C++ do PTX/SASS. Potrzebny do budowania, nie do uruchamiania. |
apt lub obraz NGC |
W czasie działania liczy się sterownik. Sterownik obsługuje maksymalną wersję runtime’u CUDA; runtime musi być w tej wersji lub starszy. Toolkit jest potrzebny tylko wtedy, gdy kompiluje się kod CUDA samodzielnie — w 95% instalacji nvcc na hoście nie jest potrzebny.
Dlatego właśnie kontenery działają: obraz niesie własny runtime CUDA, a host potrzebuje wyłącznie sterownika. Sterownik na hoście to jedyna rzecz, która musi się zgadzać. Cała reszta jest przenośna.
┌─────────────────────────────────────────────────┐
│ Container: PyTorch 2.9 + CUDA 13.0 runtime │ ← dostarczane w obrazie
│ Container: vLLM + CUDA 13.0 runtime │ ← dostarczane w obrazie
├─────────────────────────────────────────────────┤
│ Host: NVIDIA driver 570.x │ ← jedyne, czego potrzebuje host
│ Host: nvidia-container-toolkit │ ← łączy sterownik → kontener
└─────────────────────────────────────────────────┘
Ten obrazek to różnica między jednym popołudniem pracy a trzema dniami piekła zależności.
CUDA 12.x czy 13.x — co wybrać
Obie wersje są w maju 2026 aktywnie używane. Uczciwa macierz dla obciążeń, jakie obsługują serwery Kentino:
| Stos | CUDA 12.4–12.8 | CUDA 13.0+ |
|---|---|---|
| PyTorch stabilny | 2.5 / 2.6 (12.4–12.6) | 2.9 / 2.10 / 2.11 (13.0+) |
| Stabilne wheele vLLM | wheele 12.8 nadal dostarczane | 13.0 to domyślny wheel w PyPI od v0.20 |
| llama.cpp | Działa na obu | Działa na obu |
| TensorRT-LLM | Przypięte do obrazu NGC PyTorch (25.12 → 13.0) | Natywnie |
| Blackwell (5090, RTX Pro 6000, B70) | Wymaga minimum 12.8+ | Najlepiej wspierane |
| Ada (4090, L40, L4) | W pełni wspierane | W pełni wspierane |
W nowych konfiguracjach domyślnym wyborem Kentino jest CUDA 13.0. Każde GPU z oferty (5090, 4090, RTX Pro 6000 Blackwell, L40, L4) jest wspierane, vLLM domyślnie publikuje w PyPI wheele 13.0, obraz vllm/vllm-openai korzysta z 13.0, PyTorch 2.11 (z którym vLLM jest budowany) powstaje pod 13.0, a nowe funkcje (FlashAttention 3 na Blackwellu, kernele treningu FP8) celują najpierw w 13.x.
Przy 12.8 warto zostać tylko wtedy, gdy: odtwarzają Państwo przypięty benchmark, SDK producenta jeszcze nie przeszło na nowszą wersję albo w grę wchodzą wyłącznie karty sprzed Blackwella. W nowych instalacjach nic starszego niż 12.4 — błędy poprawiono upstream dwa lata temu.
Czysta instalacja sterownika i CUDA
Ubuntu 24.04 LTS (w 22.04 jest identycznie). Czystą drogą jest repozytorium apt NVIDII z CUDA:
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/x86_64/cuda-keyring_1.1-1_all.deb
sudo dpkg -i cuda-keyring_1.1-1_all.deb
sudo apt update
# Sterownik + biblioteki runtime CUDA. Bez nvcc — tylko to, czego aplikacje potrzebują do działania.
sudo apt install -y cuda-drivers-570 cuda-runtime-13-0
# Opcjonalnie pełny toolkit (nvcc, nagłówki). Tylko przy kompilacji na hoście.
# sudo apt install -y cuda-toolkit-13-0
sudo reboot
Po restarcie nvidia-smi powinno raportować sterownik 570.x i CUDA 13.0. Pułapki, których należy unikać:
-
Nie należy instalować metapakietu
cuda, chyba że chcą Państwo wszystkiego. Ściąga toolkit, przykłady, GDS, Nsight i przypina pakiety, których nikt nie zamawiał. Trzeba jawnie wybraćcuda-runtime-13-0albocuda-toolkit-13-0. -
Przypiąć sterownik, aby unattended-upgrades nie podmieniły modułu jądra:
sudo apt-mark hold cuda-drivers cuda-drivers-570 nvidia-driver-570 nvidia-dkms-570 libnvidia-compute-570. -
Jedna gałąź sterownika naraz. Mieszanie pakietów 550 i 570 daje system, który wprawdzie się uruchamia, ale
nvidia-smizwraca niejasny błąd niezgodności wersji. Naprawa toapt purge '*nvidia*' '*cuda*'i instalacja od zera — lepiej do tego nie dopuścić.
cuDNN — apt czy tarball?
cuDNN to biblioteka prymitywów głębokiego uczenia — konwolucja, attention, RNN. Zależą od niej PyTorch, TensorFlow i JAX. Od wersji 9.x są dwie drogi instalacji.
apt (zalecane):
sudo apt install -y libcudnn9-cuda-13 libcudnn9-dev-cuda-13
Instaluje się do /usr/lib/x86_64-linux-gnu/, jest wykrywane przez dynamiczny linker i integruje się z menedżerem pakietów, więc aktualizacje bezpieczeństwa przychodzą same. W jednym momencie może być zainstalowana tylko jedna wersja cuDNN 9 dla danej wersji CUDA — przez apt nie da się mieć libcudnn9-cuda-12 i libcudnn9-cuda-13 obok siebie.
Tarball:
# Pobranie z manifestu redist pod developer.download.nvidia.com/compute/cudnn/redist/
tar -xf cudnn-linux-x86_64-9.5.0.x_cuda13-archive.tar.xz
sudo cp -r cudnn-linux-x86_64-*/include/* /usr/local/cuda/include/
sudo cp -r cudnn-linux-x86_64-*/lib/* /usr/local/cuda/lib64/
Tarball ma sens przy kilku wersjach cuDNN na jednym hoście, przy pakietach dla środowisk odciętych od sieci albo przy przypinaniu konkretnej mikrowersji. W pozostałych przypadkach: apt. Dokumentacja NVIDII zaleca pakiety dystrybucyjne wszędzie tam, gdzie to możliwe — tarball nie jest instalatorem, lecz archiwum redystrybucyjnym.
Uczciwa odpowiedź: przy korzystaniu z kontenerów NGC cuDNN na hoście nie trzeba instalować w ogóle. Jest w obrazie.
Kontenery czy bare-metal — kiedy co
Największa pojedyncza decyzja w całym stosie, bez uniwersalnej odpowiedzi. Kompromis widziany na realnych konfiguracjach Kentino:
| Wymiar | Bare-metal | Kontener |
|---|---|---|
| Szczytowa przepustowość | 100% (punkt odniesienia) | 99–100% (pomijalne) |
| Czas konfiguracji | Godziny, potem tygodnie rozjeżdżania się | Minuty, obraz jest specyfikacją |
| Powtarzalność | Słaba — liczy się stan hosta | Doskonała — obraz jest zamrożony |
| Wielodostępność | Niewygodna | Natywna |
| Wiele wersji CUDA | Bolesne, jedna naraz | Trywialne, obraz na wersję |
| Debugowanie wydajności | Łatwiejsze (mniej warstw) | Trudniejsze (cgroup, przestrzenie nazw) |
| Wpływ aktualizacji sterownika | Testuje się wszystko od nowa | Testuje się tylko host |
Różnica wydajności CUDA między kontenerem a bare-metalem jest na współczesnych jądrach pomijalna — w najgorszym razie pojedyncze procenty, zwykle zwykły szum. Kto twierdzi inaczej, mierzy dysk albo sieć, a nie obliczenia na GPU.
Bare-metal: gonitwa za ostatnimi 2–3% na potrzeby publikacji, debugowanie kerneli przez cuda-gdb / compute-sanitizer / Nsight, gdy warstwa kontenera przeszkadza, albo jeden proces władający maszyną przez lata.
Kontenery (domyślny wybór Kentino): maszyny wielu użytkowników, PyTorch 2.5 i 2.11 obok siebie, podmiana frameworków inferencyjnych (vLLM, SGLang, TensorRT-LLM) bez przebudowy hosta albo wdrożenie, które można docker pull na nowy serwer i mieć uruchomione w pięć minut.
Dla laboratorium robotyki lub grupy badawczej: kontenery. Dla stanowiska benchmarkowego z jednym obciążeniem bare-metal jest w zupełności wystarczający.
nvidia-container-toolkit — czym jest i jak go skonfigurować
Toolkit to klej dający kontenerowi dostęp do GPU hosta. Bez niego nvidia-smi w kontenerze nie działa. Z nim kontener widzi sterownik, urządzenia i wstrzyknięty stub runtime’u.
Instalacja:
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 update && sudo apt install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
# Test kontrolny
docker run --rm --gpus all nvidia/cuda:13.0.0-base-ubuntu24.04 nvidia-smi
To ostatnie polecenie powinno pokazać z wnętrza kontenera wyjście nvidia-smi z hosta. Jeśli tak jest, stos jest poprawnie spięty.
Podman
Podman korzysta z CDI:
sudo nvidia-ctk runtime configure --runtime=podman
sudo nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml
podman run --rm --device=nvidia.com/gpu=all \
nvcr.io/nvidia/pytorch:25.12-py3 nvidia-smi
Podman w trybie rootless + CDI to najczystsza konfiguracja dla maszyn wielu użytkowników, gdy nie chcą Państwo dodawać ich do grupy docker (co w praktyce równa się rootowi).
CDI a klasyczny runtime
Dwa tryby udostępniania GPU:
-
Klasyczny hook runtime’u
nvidia— to, z czego--gpus allkorzysta od lat. Docker wywołuje hook, który w czasie uruchomienia montuje do kontenera biblioteki sterownika i urządzenia. -
CDI (Container Device Interface) — otwarta specyfikacja deklarowania dostępu do urządzeń.
nvidia-ctk cdi generatezapisuje plik YAML wyliczający GPU jako nazwane urządzenia (nvidia.com/gpu=0,nvidia.com/gpu=all); korzysta z nich każdy runtime obsługujący CDI.
Stan na połowę 2026:
| Tryb | Docker | Podman | Kubernetes (GPU Operator) | Rootless |
|---|---|---|---|---|
| Klasyczny | Domyślny, działa | Działa | Przestarzały | Bolesny |
| CDI | Wspierany | Domyślny | Domyślny od v25.10 | Czysty |
Przy instalacji Dockera na pojedynczym serwerze tryb klasyczny nadal działa dobrze. Wszędzie tam, gdzie w grę wchodzi Kubernetes, tryb rootless albo wielu użytkowników, warto przejść na CDI — to tam idą inwestycje NVIDII. Migracja jest nieinwazyjna: instalacja toolkitu, wygenerowanie specyfikacji CDI, zamiana --gpus all na --device=nvidia.com/gpu=all. Oba tryby mogą współistnieć.
Przekazywanie GPU — co naprawdę robi --gpus all
Po uruchomieniu docker run --gpus all my-image hook runtime’u odczytuje NVIDIA_VISIBLE_DEVICES / NVIDIA_DRIVER_CAPABILITIES, montuje /dev/nvidia* do kontenera wraz z uprawnieniami cgroup, podmontowuje pliki .so sterownika hosta i ustawia LD_LIBRARY_PATH, aby linker je odnalazł.
Co pozostaje pod kontrolą:
docker run --gpus all ... # wszystkie GPU
docker run --gpus '"device=0,1"' ... # po indeksie
docker run --gpus '"device=GPU-abc123..."' ... # po UUID
docker run --gpus all -e NVIDIA_DRIVER_CAPABILITIES=compute,utility ...
docker run --device=nvidia.com/gpu=0 --device=nvidia.com/gpu=1 ... # CDI
Na serwerze z 8 GPU i vLLM w trybie tensor-parallel należy użyć --gpus all. Na maszynie wielodostępnej, gdzie użytkownicy dostają wycinki po 4 GPU, trzeba przypinać po UUID — przypinanie po indeksie przestaje działać po przepięciu okablowania.
Kontenery NGC — kiedy po nie sięgać
Katalog NGC od NVIDII (nvcr.io) udostępnia obrazy m.in. dla PyTorcha, TensorRT, TensorRT-LLM i Tritona. Są duże (5–15 GB), ale przetestowane i dostarczane z zestawami cuDNN / NCCL / runtime CUDA, które przeszły QA NVIDII. Maj 2026:
| Obraz | Zawiera |
|---|---|
nvcr.io/nvidia/pytorch:25.12-py3 |
PyTorch 2.9.1 + CUDA 13.0 + cuDNN 9 + NCCL |
nvcr.io/nvidia/tritonserver:25.12-py3 |
Triton + backendy Python / ONNX / TensorRT / vLLM |
nvcr.io/nvidia/tensorrt-llm/release:0.x |
Build TensorRT-LLM, zoptymalizowane silniki, NCCL |
nvcr.io/nvidia/tensorrt:25.08-py3 |
TensorRT C++ / Python, parser ONNX |
Tagi mają postać <year>.<month>-py3, wydawane co miesiąc. Nie są dokładnie tym, co upstream — są łatane i przebudowywane — ale trzymają się blisko.
Uczciwy argument za NGC: przy TensorRT-LLM albo Tritonie warto wziąć obraz NGC. Praca dopasowania cuDNN, NCCL, TensorRT i CUDA jest już wykonana. Dla upstreamowego PyTorcha czy vLLM publiczne obrazy (pytorch/pytorch:..., vllm/vllm-openai:...) są mniejsze i szybciej aktualizowane — NGC to przerost formy.
MIG — i dlaczego nie dotyczy oferty Kentino
MIG dzieli jedno GPU na maksymalnie siedem odizolowanych wycinków, każdy z własną pamięcią, mocą obliczeniową i domeną awarii. Przydaje się przy inferencji wielodostępnej — pięciu użytkowników dostaje po 1/7 H100 z twardą izolacją.
MIG nie jest dostępny na kartach konsumenckich (RTX 5090, 4090) ani na kartach Blackwell do stacji roboczych (RTX Pro 6000). Jest zastrzeżony dla modeli datacenter — H100, H200, A100, B100, B200, GB200. Kentino nie sprowadza GPU datacenter w formacie SXM, więc MIG nie występuje w żadnej konfiguracji Kentino.
Zamiennikiem na kartach konsumenckich i kartach do stacji roboczych jest MPS (Multi-Process Service) — wiele procesów dzieli wtedy harmonogram obliczeń GPU. To nie jest izolacja na poziomie MIG (jeden niesforny proces potrafi wywołać OOM na całym urządzeniu), ale przy zaufanej inferencji wielodostępnej sprawdza się i nic nie kosztuje. Jeśli MIG jest naprawdę niezbędny, potrzebna jest linia SKU datacenter od innego integratora.
Rozwiązywanie problemów — błędy, które dopadają każdego
CUDA error: no kernel image is available for execution on the device (błąd 209). Runtime CUDA w kontenerze nie ma kerneli dla compute capability danego GPU — zwykle obraz z CUDA 12.4 na karcie Blackwell (sm_120), która wymaga 12.8+. Naprawa: nowszy obraz albo kompilacja z właściwym TORCH_CUDA_ARCH_LIST.
CUDA error: forward compatibility was attempted on non supported HW (błąd 100). Sterownik na hoście jest starszy, niż wymaga runtime w kontenerze. Naprawa: aktualizacja sterownika na hoście — z repozytorium NVIDII, a nie z przestarzałej paczki Ubuntu.
Failed to initialize NVML: Driver/library version mismatch. Sterownik zaktualizowany przez apt bez restartu; moduł jądra jest stary, przestrzeń użytkownika nowa. Naprawa: restart. (Jeśli restart nie wchodzi w grę, można zrobić rmmod modułom nvidia i modprobe je z powrotem — ale restart jest bezpieczniejszy.)
nvidia-container-cli: initialization error: nvml error: driver not loaded. Toolkit zainstalowany, ale moduł jądra sterownika nie jest załadowany. Zwykle świeża instalacja, w której nvidia-smi na samym hoście już nie działa. Najpierw host, potem kontener.
OCI runtime exec failed: ... no such file or directory przy --gpus all. Hook runtime’u nie jest zarejestrowany w Dockerze. Należy ponownie wykonać sudo nvidia-ctk runtime configure --runtime=docker && sudo systemctl restart docker. Jeśli to nie pomoże, warto sprawdzić w /etc/docker/daemon.json blok "runtimes".
Budowanie ze źródeł czy gotowe paczki
PyTorch, vLLM, llama.cpp, FlashAttention — wszystkie mają gotowe wheele i obrazy. Ze źródeł warto budować tylko wtedy, gdy potrzebna jest niewydana funkcja, gdy compute capability nie jest objęte przez wheele upstream albo gdy kompiluje się pod własne CUDA / cuDNN. PyTorch ze źródeł to 30–90 minut na EPYC-u i zero zysku wydajności, o ile nie przekaże się własnych flag CMake. Budowanie ze źródeł jest odpowiedzią na konkretny problem, a nie ustawieniem domyślnym.
Co zrobić dalej
Dla serwera Kentino budowanego od zera:
- Instalacja Ubuntu LTS i przypięcie sterownika zgodnie z L01.
- Instalacja
cuda-runtime-13-0(pełny toolkit można pominąć, o ile nic nie jest kompilowane). - Instalacja
libcudnn9-cuda-13przez apt — albo pominięcie tego kroku przy pełnej konteneryzacji. - Instalacja
nvidia-container-toolkit, konfiguracja Dockera i test kontrolny:docker run --rm --gpus all nvidia/cuda:13.0.0-base-ubuntu24.04 nvidia-smi. - Pobranie obrazu pod własne obciążenie:
vllm/vllm-openai:latest,nvcr.io/nvidia/pytorch:25.12-py3lubnvcr.io/nvidia/tritonserver:25.12-py3. - Uruchamianie z
--gpus allalbo przejście na CDI od razu, jeśli na horyzoncie jest tryb wielu użytkowników, rootless lub Kubernetes. -
apt-mark holdna sterowniku — i nigdyapt-get dist-upgradena działającym serwerze.
L03 opisuje strojenie jądra, L04 omawia wybór systemu plików pod przechowywanie modeli i przepustowość checkpointów, a L05 opisuje stos monitoringu (Prometheus, Grafana, DCGM-exporter). Jeśli nvidia-smi działa już dziś w kontenerze na Państwa maszynie, to 80% drogi jest za Państwem.
To część Kentino Wiki, serii referencyjnej o obliczeniach AI, robotyce i systemach, które je łączą. Komentarze i poprawki mile widziane pod adresem info@kentino.com.