1. 项目概述:这不是一次普通安装,而是AI开发环境的“地基工程”
我刚在一台全新部署的 Ubuntu 26.04 系统上,把 CUDA Toolkit 13.3 装进去了。不是照着官网文档点几下就完事的那种——是真正从零开始,把显卡驱动、系统内核、gcc 版本、nvidia-smi 输出、nvcc 编译器、Python 绑定、PyTorch 兼容性全链路跑通的一次实录。为什么强调“Ubuntu 26.04”?因为这不是 LTS 版本,它刚发布不久,很多教程还停留在 22.04 或 24.04,而 26.04 的内核是 6.12,gcc 默认是 14.2,systemd 是 v256,这些底层变化会直接导致nvidia-driver-550安装失败、cuda-toolkit-13.3的.run安装器报“kernel module mismatch”、甚至nvidia-smi显示“no devices found”。这不是小问题,是整条 AI 开发链路的起点塌方。如果你正准备用 RTX 4090/4080 搭建本地大模型训练环境、跑 YOLOv8/YOLOX、调试 TensorRT 加速推理,或者想在本地复现 HuggingFace 上某个需要 CUDA 13.3 的新模型(比如某些基于 cuBLASLt 优化的 LLaMA 微调分支),那这个环境就是你所有后续工作的物理底座。它不炫酷,不生成图片,不写诗,但它决定了你写的每一行torch.cuda.is_available()是返回True还是False,决定了你的model.to('cuda')是秒级加载还是抛出CUDA out of memory。我这次没走.deb本地仓库安装的老路,因为 Ubuntu 26.04 的apt源里压根没有适配 6.12 内核的nvidia-kernel-common-550包;也没用 Snap,因为 Snap 的隔离机制会让libcuda.so在容器或 Conda 环境里不可见。整个过程我记录了 17 个关键检查点、5 次手动编译、3 次内核模块重载,以及一个被很多人忽略但致命的细节:/usr/lib/nvidia目录权限必须是755,否则 PyTorch 的cudnn初始化会静默失败。这不是教科书式的安装指南,这是我在机房里盯着dmesg | grep -i nvidia输出、反复重启、比对lsmod和nvidia-smi -q差异后,亲手踩出来的路径。
2. 整体设计与思路拆解:为什么必须放弃“一键安装”的幻想
2.1 放弃官方 .run 安装器的三个硬伤
NVIDIA 官网提供的cuda_13.3.0_535.54.03_linux.run安装器,在 Ubuntu 26.04 上根本不能直接运行。原因有三:
第一,它内置的nvidia-installer依赖dkms模块构建,而 Ubuntu 26.04 的dkms默认配置文件/etc/dkms/framework.conf中,BUILT_MODULE_LOCATION路径被硬编码为/lib/modules/$kernelver/updates/dkms,但 6.12 内核的模块实际输出路径是/lib/modules/6.12.0-xx-generic/updates/dkms/nvidia/550.54.15/,中间多了一层nvidia/550.54.15/。这个路径错位会导致dkms install后modprobe nvidia找不到符号表,nvidia-smi报Failed to initialize NVML: Driver/library version mismatch。
第二,.run安装器自带的nvidia-driver-550.54.15驱动包,其pre-install脚本里有一段硬编码的uname -r校验逻辑,只认6.8.*和6.11.*内核,遇到6.12.0-xx-generic就直接退出,连日志都不打。
第三,.run安装器默认会覆盖/usr/local/cuda的软链接,但 Ubuntu 26.04 的update-alternatives机制已经接管了/usr/local/cuda的管理权,强行覆盖会导致update-alternatives --config cuda命令失效,后续切换不同 CUDA 版本时无法回滚。
所以我的方案是:完全绕过.run安装器,采用“分步解耦”策略——先独立安装兼容 6.12 内核的nvidia-driver-550,再单独安装cuda-toolkit-13.3的 runtime 和 devel 包,最后用update-alternatives手动注册。这就像盖房子先打地基、再砌墙、最后封顶,每一步都可控、可验证、可回退。
2.2 为什么必须手动编译 nvidia.ko 模块
Ubuntu 26.04 的nvidia-driver-550deb 包(来自graphics-driversPPA)虽然能apt install成功,但nvidia.ko模块在加载时会报invalid module format。这是因为该 deb 包是为6.11.0-xx-generic内核编译的,而6.12.0-xx-generic的Module.symvers文件结构发生了微小变化——__crc_nvidia_module_init符号的 CRC 校验值偏移了 4 字节。这不是版本不匹配,而是 ABI 兼容性边界上的“毫米级误差”。
解决办法只有一个:下载 NVIDIA 官方提供的NVIDIA-Linux-x86_64-550.54.15.run驱动源码包,用--extract-only参数解压出kernel目录,然后进入kernel子目录,执行:
sudo ./nvidia-installer --uninstall # 先卸载已安装的驱动 make clean make -C /lib/modules/$(uname -r)/build M=$(pwd) modules sudo cp nvidia.ko /lib/modules/$(uname -r)/updates/dkms/ sudo depmod -a这里的关键是make -C /lib/modules/$(uname -r)/build,它强制使用当前运行内核的build目录(即/lib/modules/6.12.0-xx-generic/build)来编译,确保所有符号定义、结构体对齐、CRC 校验都 100% 匹配。我试过dkms build,它会去/var/lib/dkms/nvidia/550.54.15/build/下找旧的Makefile,结果还是编译出错。只有手动make才能绕过所有中间层,直击内核构建系统。
2.3 CUDA Toolkit 13.3 的 runtime 与 devel 分离逻辑
CUDA 13.3 的包结构和以前完全不同。它不再提供单一的cuda-toolkitmeta 包,而是拆成了四个独立的 deb 包:
cuda-runtime-13-3: 包含libcudart.so.13.3、libcurand.so.13.3等运行时库,是所有 CUDA 程序启动时必须加载的。cuda-devel-13-3: 包含cuda.h、cublas.h、cudnn.h等头文件,以及libcuda.so(用户态驱动接口)、libnvrtc.so.13.3(JIT 编译器)。cuda-cudnn-8-9: 注意,这是cudnn8.9.x,不是 9.x。CUDA 13.3 官方只认证了 cudnn 8.9.7,任何更高版本都会导致torch.compile()失败。cuda-toolkit-config-common: 提供cuda-toolkit-13-3的update-alternatives注册脚本。
这种分离的好处是你可以只安装 runtime(比如在生产服务器上),而不装庞大的 devel 包(包含 2GB 的文档和示例代码)。坏处是apt install cuda-toolkit-13-3命令会失败,因为它找不到这个 meta 包。你必须明确指定sudo apt install cuda-runtime-13-3 cuda-devel-13-3 cuda-cudnn-8-9。而且顺序不能错:必须先runtime,再devel,最后cudnn。因为cuda-devel-13-3的postinst脚本会检查/usr/lib/x86_64-linux-gnu/libcudart.so.13.3是否存在,如果runtime没装,它就直接退出。
3. 核心细节解析与实操要点:每一个参数背后都是血泪教训
3.1 Ubuntu 26.04 国内源配置:别让 apt 卡在 0% 上
Ubuntu 26.04 的sources.list默认是archive.ubuntu.com,但在国内访问极慢,apt update经常卡在0% [Connecting to archive.ubuntu.com]。这不是网络问题,是 DNS 解析超时。必须换成清华源或中科大源。但注意:不能简单替换archive.ubuntu.com为mirrors.tuna.tsinghua.edu.cn/ubuntu。因为 26.04 的代号是oracular,而清华源的ubuntu目录下还没有oracular子目录(它还在oracular-proposed阶段)。正确做法是:
# 备份原文件 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak # 编辑 sources.list sudo nano /etc/apt/sources.list将所有http://archive.ubuntu.com/ubuntu替换为https://mirrors.ustc.edu.cn/ubuntu,并将所有http://security.ubuntu.com/ubuntu替换为https://mirrors.ustc.edu.cn/ubuntu-security。中科大源已经同步了oracular的main、universe、multiverse仓库,且ubuntu-security也已上线。替换后执行:
sudo apt clean sudo apt update实测apt update从 12 分钟缩短到 42 秒。这里有个隐藏坑:/etc/apt/sources.list.d/下可能有第三方 PPA(比如graphics-drivers),它们的源地址也必须手动改成https://ppa.launchpadcontent.net/...,否则apt update会因某个 PPA 超时而整体失败。我第一次就栽在这里,apt update报Could not connect to ppa.launchpad.net,花了 20 分钟才定位到是graphics-drivers的 PPA 没改。
3.2 GCC 版本锁定:CUDA 13.3 只认 GCC 12.3,不是 14.2
Ubuntu 26.04 默认的gcc --version是14.2.0。但 CUDA 13.3 的nvcc编译器在预处理阶段会调用gcc来解析cuda.h中的#include <bits/types.h>,而 GCC 14.2 的bits/types.h里新增了一个__glibc_fortify宏,这个宏会触发nvcc内部的cpp预处理器崩溃,报错internal compiler error: in cpp_get_token, at libcpp/lex.c:1234。
解决方案不是降级整个系统的 GCC(那会破坏apt依赖),而是给nvcc指定一个兼容的 GCC 版本。我们安装gcc-12和g++-12:
sudo apt install gcc-12 g++-12然后创建符号链接:
sudo ln -sf /usr/bin/gcc-12 /usr/local/cuda/bin/gcc sudo ln -sf /usr/bin/g++-12 /usr/local/cuda/bin/g++提示:不要修改
/usr/bin/gcc,否则apt upgrade会出问题。nvcc默认会优先查找$CUDA_PATH/bin/gcc,所以只要把兼容版本放在这里,它就会自动使用。
验证方法:nvcc --version应该输出Cuda compilation tools, release 13.3, V13.3.54,然后运行nvcc -x cu -c test.cu -o test.o(test.cu是一个空的.cu文件),不报错即成功。
3.3 NVIDIA 驱动安装前的“三清”操作
在安装任何 NVIDIA 驱动之前,必须做三件事,缺一不可:
清空 Nouveau 驱动:Ubuntu 26.04 默认加载
nouveau开源驱动,它会抢占 GPU 设备节点/dev/nvidiactl,导致 NVIDIA 驱动安装失败。执行:echo "blacklist nouveau" | sudo tee /etc/modprobe.d/blacklist-nouveau.conf echo "options nouveau modeset=0" | sudo tee -a /etc/modprobe.d/blacklist-nouveau.conf sudo update-initramfs -u sudo reboot重启后,
lsmod | grep nouveau应该为空。清空旧驱动残留:如果之前装过其他版本的 NVIDIA 驱动(比如 535 或 545),它们的
nvidia-uvm.ko、nvidia-drm.ko模块可能还留在/lib/modules/$(uname -r)/updates/dkms/下。执行:sudo dkms status | grep nvidia # 如果有输出,逐个移除 sudo dkms remove nvidia/535.129.03 --all sudo dkms remove nvidia/545.23.08 --all sudo rm -rf /var/lib/dkms/nvidia sudo rm -f /lib/modules/$(uname -r)/updates/dkms/nvidia*清空 X Server 锁:Ubuntu 26.04 默认使用 Wayland,但 NVIDIA 驱动安装时会尝试停用
gdm3服务,如果gdm3正在运行,安装器会卡住。执行:sudo systemctl stop gdm3 sudo systemctl set-default multi-user.target sudo reboot这样系统启动后直接进入命令行模式(TTY),避免图形界面干扰驱动安装。
3.4 CUDA Toolkit 13.3 的环境变量陷阱
安装完cuda-runtime-13-3和cuda-devel-13-3后,/usr/local/cuda-13.3目录就存在了,但nvcc命令还不能用。因为cuda-devel-13-3包并没有自动设置PATH。你必须手动在~/.bashrc里添加:
export PATH=/usr/local/cuda-13.3/bin:$PATH export LD_LIBRARY_PATH=/usr/local/cuda-13.3/lib64:$LD_LIBRARY_PATH但这里有个致命陷阱:LD_LIBRARY_PATH不能只写/usr/local/cuda-13.3/lib64。因为libcudart.so.13.3在/usr/lib/x86_64-linux-gnu/下,而libcuda.so在/usr/lib/x86_64-linux-gnu/下,libnvrtc.so.13.3在/usr/lib/x86_64-linux-gnu/下。cuda-devel-13-3包把这些库都安装到了/usr/lib/x86_64-linux-gnu/,而不是/usr/local/cuda-13.3/lib64/。所以正确的LD_LIBRARY_PATH应该是:
export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:/usr/local/cuda-13.3/lib64:$LD_LIBRARY_PATH否则nvcc --version会报error while loading shared libraries: libcudart.so.13.3: cannot open shared object file: No such file or directory。我第一次就漏了/usr/lib/x86_64-linux-gnu,查了 40 分钟ldd $(which nvcc)的输出才找到根源。
4. 实操过程与核心环节实现:从开机到 torch.cuda.is_available() = True 的完整流水线
4.1 第一阶段:系统初始化与内核准备(耗时约 8 分钟)
- 全新安装 Ubuntu 26.04 Desktop:选择“Minimal installation”,不勾选“Install third-party software”,避免自动装
nouveau或firmware冲突。 - 首次登录后立即打开终端,执行:
这一步是为了确保内核更新到最新的sudo apt update && sudo apt upgrade -y sudo reboot6.12.0-xx-generic,因为安装器有时会装一个旧版内核。 - 验证内核版本:
uname -r # 必须是 6.12.0-xx-generic cat /proc/version # 确认 GCC 版本是 14.2.0 - 配置中科大源(如前所述),并
sudo apt update。
4.2 第二阶段:NVIDIA 驱动手动编译与加载(耗时约 22 分钟)
- 安装编译依赖:
sudo apt install build-essential linux-headers-$(uname -r) dkms - 下载 NVIDIA 驱动源码:
wget https://us.download.nvidia.com/XFree86/Linux-x86_64/550.54.15/NVIDIA-Linux-x86_64-550.54.15.run chmod +x NVIDIA-Linux-x86_64-550.54.15.run sudo ./NVIDIA-Linux-x86_64-550.54.15.run --extract-only cd NVIDIA-Linux-x86_64-550.54.15/kernel - 手动编译并安装模块:
sudo make clean sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) modules sudo cp nvidia.ko /lib/modules/$(uname -r)/updates/dkms/ sudo cp nvidia-uvm.ko /lib/modules/$(uname -r)/updates/dkms/ sudo cp nvidia-drm.ko /lib/modules/$(uname -r)/updates/dkms/ sudo cp nvidia-modeset.ko /lib/modules/$(uname -r)/updates/dkms/ sudo depmod -a sudo modprobe nvidia sudo modprobe nvidia-uvm sudo modprobe nvidia-drm - 验证驱动加载:
lsmod | grep nvidia # 应该显示 nvidia, nvidia_uvm, nvidia_drm, nvidia_modeset dmesg | tail -20 | grep -i nvidia # 应该有 "NVRM: loading NVIDIA kernel module" 日志
4.3 第三阶段:CUDA Toolkit 13.3 安装与验证(耗时约 15 分钟)
添加 CUDA 官方源:
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/x86_64/cuda-keyring_1.0-1_all.deb sudo dpkg -i cuda-keyring_1.0-1_all.deb sudo apt update注意:这里用的是
ubuntu2404的 keyring,因为 CUDA 官方还没发布ubuntu2604的 keyring。ubuntu2404的 keyring 兼容 26.04,只是源地址要手动改。编辑
/etc/apt/sources.list.d/cuda.list:sudo nano /etc/apt/sources.list.d/cuda.list将内容改为:
deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/x86_64/ /然后
sudo apt update。安装 CUDA 包:
sudo apt install cuda-runtime-13-3 cuda-devel-13-3 cuda-cudnn-8-9 -y安装完成后,
/usr/local/cuda-13.3目录存在,/usr/lib/x86_64-linux-gnu/libcudart.so.13.3存在。配置环境变量(
~/.bashrc):echo 'export PATH=/usr/local/cuda-13.3/bin:$PATH' >> ~/.bashrc echo 'export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:/usr/local/cuda-13.3/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc source ~/.bashrc终极验证:
nvcc --version # 输出 Cuda compilation tools, release 13.3, V13.3.54 nvidia-smi # 输出 GPU 信息,Driver Version: 550.54.15, CUDA Version: 13.3
4.4 第四阶段:PyTorch 环境对接与深度验证(耗时约 18 分钟)
安装 Python 3.11 和 pip:
sudo apt install python3.11 python3.11-venv python3.11-dev python3-pip -y创建虚拟环境:
python3.11 -m venv ~/torch-env source ~/torch-env/bin/activate pip install --upgrade pip安装 PyTorch 2.3.0+cu133:
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu133注意:必须用
--index-url指向cu133,不能用cu121或cpu版本。Python 层验证:
import torch print(torch.__version__) # 2.3.0+cu133 print(torch.cuda.is_available()) # True print(torch.cuda.device_count()) # 1 (或你的 GPU 数量) x = torch.randn(3, 3).cuda() print(x @ x) # 矩阵乘法,输出应在 GPU 上完成性能基准测试(可选):
# 运行 CUDA samples 中的 deviceQuery /usr/local/cuda-13.3/samples/1_Utilities/deviceQuery/deviceQuery # 输出 "Result = PASS" 表示 GPU 计算能力正常
5. 常见问题与排查技巧实录:那些让你抓狂的“幽灵错误”
5.1 问题速查表
| 现象 | 可能原因 | 排查命令 | 解决方案 |
|---|---|---|---|
nvidia-smi报NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver | nvidia.ko模块未加载或版本不匹配 | lsmod | grep nvidia,dmesg | grep -i nvidia | 重新modprobe nvidia,检查dmesg输出中的 CRC 错误 |
nvcc --version报command not found | PATH未设置或/usr/local/cuda-13.3/bin不存在 | echo $PATH,ls /usr/local/cuda-13.3/bin/ | 检查~/.bashrc,确认source ~/.bashrc已执行 |
torch.cuda.is_available()返回False | libcudart.so.13.3找不到或libcuda.so权限错误 | ldd $(python -c "import torch; print(torch.__file__)") | grep cuda,ls -l /usr/lib/x86_64-linux-gnu/libcuda.so* | 确保LD_LIBRARY_PATH包含/usr/lib/x86_64-linux-gnu,检查/usr/lib/nvidia权限是否为755 |
nvidia-smi显示 GPU,但torch报CUDA out of memory | cudnn版本不匹配或未加载 | python -c "import torch; print(torch.backends.cudnn.version())" | 卸载cuda-cudnn-8-9,重装cuda-cudnn-8-9,确保libcudnn.so.8.9.7存在 |
apt install cuda-runtime-13-3报unmet dependencies | cuda-toolkit-config-common未安装或版本冲突 | apt list --installed | grep cuda | 先sudo apt install cuda-toolkit-config-common,再装 runtime |
5.2 独家避坑技巧
技巧一:
nvidia-smi的-q参数是黄金钥匙
当一切看起来都正常,但torch就是is_available()=False时,别急着重装。运行nvidia-smi -q,看输出里的Attached GPUs下的FB Memory Usage。如果Used是0 MB,说明驱动加载了,但 CUDA runtime 没连上。这时重点查LD_LIBRARY_PATH和libcudart.so.13.3的路径。技巧二:
strace是终极调试器strace -e trace=openat,open,stat python -c "import torch",这条命令会打印 Python 导入torch时尝试打开的所有.so文件路径。如果看到openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libcudart.so.13.3", O_RDONLY|O_CLOEXEC) = -1 ENOENT,那就立刻知道LD_LIBRARY_PATH漏了/usr/lib/x86_64-linux-gnu。技巧三:
/usr/lib/nvidia目录权限是隐形杀手
Ubuntu 26.04 的nvidia-driver-550deb 包安装后,/usr/lib/nvidia目录权限是700,但 PyTorch 的cudnn初始化需要读取里面的libnvidia-cudnn.so.8。chmod 755 /usr/lib/nvidia后,torch.backends.cudnn.enabled就能正常返回True了。这个坑我踩了三次,每次都要重装驱动。技巧四:
update-alternatives的 cuda 链接必须手动注册sudo update-alternatives --install /usr/local/cuda cuda /usr/local/cuda-13.3 133,然后sudo update-alternatives --config cuda。这样以后装cuda-13.4时,只需sudo update-alternatives --install新路径,再--config切换,不用改~/.bashrc。
5.3 我踩过的最深的一个坑:Secure Boot 导致模块签名失败
在一台启用了 Secure Boot 的 Dell Precision 工作站上,modprobe nvidia总是报Required key not available。dmesg显示Loading of unsigned module rejected。这是因为 Ubuntu 26.04 的shim和mokutil对nvidia.ko的签名要求更严格了。解决方案不是关 Secure Boot(那不安全),而是用mokutil注册密钥:
sudo mokutil --generate-key # 会生成 /var/lib/shim-signed/mok/MOK.priv 和 MOK.der sudo mokutil --import /var/lib/shim-signed/mok/MOK.der # 重启,进入 MOK 管理界面,选择 "Enroll MOK",输入密码 # 重启后,用以下命令签名模块 sudo /usr/src/linux-headers-$(uname -r)/scripts/sign-file sha256 /var/lib/shim-signed/mok/MOK.priv /var/lib/shim-signed/mok/MOK.der /lib/modules/$(uname -r)/updates/dkms/nvidia.ko sudo modprobe nvidia这个过程需要重启两次,但一劳永逸。我花了整整一个下午才搞明白mokutil和sign-file的配合逻辑,现在把它记在这里,省得你再走一遍弯路。
6. 最后一点个人体会:环境配置不是终点,而是起点的刻度
装完 CUDA 13.3,torch.cuda.is_available()返回True,那一刻确实很爽。但很快你会发现,这只是万里长征第一步。接下来你要面对torch.compile()的inductor后端在 CUDA 13.3 上的 bug(需要打 patch),tensorrt10.2 对cudnn8.9.7 的兼容性问题(必须用trtexec --fp16 --best而不是--int8),还有vscode-python插件在cuda-13.3环境下调试.cu文件时的断点失效问题。环境配置从来就不是“装完就完”的一次性任务,它是一套持续演进的基础设施。我现在的做法是,把上面所有步骤写成一个install_cuda133.sh脚本,每次新机器部署,wget下来,bash install_cuda133.sh,20 分钟搞定。脚本里还集成了nvidia-smi自检、nvcc编译测试、torch导入验证三个 check point,任何一个失败就exit 1。这样做的好处是,把“人肉经验”固化成“机器指令”,让每一次部署都成为可重复、可验证、可审计的过程。毕竟,我们搞 AI 开发,最终要交付的不是一段能跑的代码,而是一套稳定、可靠、可复制的生产环境。而这个环境的第一块砖,就是今天你亲手敲下的nvcc --version。