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-0 albo cuda-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-smi zwraca niejasny błąd niezgodności wersji. Naprawa to apt 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 all korzysta 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 generate zapisuje 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:

  1. Instalacja Ubuntu LTS i przypięcie sterownika zgodnie z L01.
  2. Instalacja cuda-runtime-13-0 (pełny toolkit można pominąć, o ile nic nie jest kompilowane).
  3. Instalacja libcudnn9-cuda-13 przez apt — albo pominięcie tego kroku przy pełnej konteneryzacji.
  4. Instalacja nvidia-container-toolkit, konfiguracja Dockera i test kontrolny: docker run --rm --gpus all nvidia/cuda:13.0.0-base-ubuntu24.04 nvidia-smi.
  5. Pobranie obrazu pod własne obciążenie: vllm/vllm-openai:latest, nvcr.io/nvidia/pytorch:25.12-py3 lub nvcr.io/nvidia/tritonserver:25.12-py3.
  6. Uruchamianie z --gpus all albo przejście na CDI od razu, jeśli na horyzoncie jest tryb wielu użytkowników, rootless lub Kubernetes.
  7. apt-mark hold na sterowniku — i nigdy apt-get dist-upgrade na 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.