Technical note

Ubuntu下搭建CUDA与容器GPU工具链

这台Ubuntu22.04主机既要使用CUDA进行本机开发,也要让Docker容器调用GPU。整套环境除了Toolkit,还涉及驱动、cuDNN和NVIDIAContainerToolkit,其中最容易出问题的是几组版本之间的兼容关系。

下载地址

先核对版本

驱动、CUDA和GCC的对应关系会变化,直接查当前版本的ReleaseNotes比保存一张静态大表可靠:

先看机器上的现状:

nvidia-smi
command -v nvcc && nvcc --version
ls -ld /usr/local/cuda* 2>/dev/null

nvidia-smi顶部的CUDAVersion是驱动支持的最高CUDA版本,不代表已经安装了同版本的Toolkit。Toolkit版本以nvcc --version和安装目录为准。

使用Runfile安装CUDA

Runfile适合离线安装或固定版本。能使用APT的机器还是优先用软件包,后续卸载和内核升级都省事一些。

先安装编译工具和当前内核头文件:

sudo apt-get update
sudo apt-get install -y build-essential linux-headers-"$(uname -r)"

下载完成后核对校验值,再运行安装器:

sha256sum cuda_<version>_linux.run
sudo sh cuda_<version>_linux.run

如果驱动已经通过APT或单独的Runfile装好,在交互界面中取消Driver,只安装CUDAToolkit。不要让两种安装方式同时管理驱动。

安装完成后按实际目录配置环境变量:

export PATH=/usr/local/cuda-X.Y/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda-X.Y/lib64:${LD_LIBRARY_PATH:-}

确认nvcc --version正常后,再写入Shell配置文件。

早期配置曾直接修改/usr/bin/gcc软链接来切换GCC。这会影响系统中其他编译任务,现在更合适的做法是并行安装所需版本,并在构建时单独指定:

CC=/usr/bin/gcc-X CXX=/usr/bin/g++-X cmake -S . -B build

Runfile安装的Toolkit可以使用自带卸载器删除:

sudo /usr/local/cuda-X.Y/bin/cuda-uninstaller

cuDNN

cuDNN还要单独核对CUDA版本和系统支持范围:

当前系统如果已经配置NVIDIA软件源,可以直接安装与CUDA主版本对应的软件包。例如cuDNN9配合CUDA12:

sudo apt-get update
sudo apt-get install -y cudnn9-cuda-12

Docker中使用GPU

旧的nvidia-container-runtime仓库已经归档,现在使用nvidia-container-toolkit。这里有一个容易混淆的地方:容器使用宿主机的GPU驱动,CUDA用户态库通常放在镜像里,所以镜像版本仍然受宿主机驱动限制。

Ubuntu下配置APT仓库:

sudo apt-get update
sudo apt-get install -y --no-install-recommends \
  ca-certificates curl gnupg2

curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \
  | sudo gpg --dearmor \
    -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg

curl -sL 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

安装并写入Docker运行时配置:

sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker

nvidia-ctk会修改/etc/docker/daemon.json,已有自定义配置时先备份这个文件。

NVIDIACUDA镜像标签中选一个宿主机驱动支持的版本进行验证:

docker run --rm --gpus all \
  nvidia/cuda:<toolkit-tag>-base-ubuntu22.04 \
  nvidia-smi

宿主机的nvidia-smi正常、容器中却找不到GPU时,检查Docker运行时和Toolkit版本:

docker info | sed -n '/Runtimes/,+3p'
nvidia-ctk --version
journalctl -u docker -n 100 --no-pager

参考资料