1. 为什么这套"老版本三件套"至今还有人折腾
先把结论摆在前面:CUDA 10.2 + cuDNN 8 + TensorRT 6.0 这套组合,放在今天看确实不算新,但它并没有彻底退出历史舞台。我最近就碰到一个很典型的场景——某实验室的一台工控机,显卡是 Tesla P4,系统锁死在 Ubuntu 18.04,配套的推理服务又依赖 TensorRT 6.0 的某个算子实现。你没法随便升级,因为一升级整条链路全崩。这种"被版本锁死"的情况在工业部署、边缘设备、老项目维护里非常常见。
所以这篇东西不是写给追新的人看的,而是写给那些手里有一台 Ubuntu 18.04、一块老卡、一个跑不动的推理服务的人。整套流程的核心难点其实不在"装",而在"配"——CUDA、cuDNN、TensorRT 三者之间有严格的版本对应关系,装错一个版本,后面全是玄学报错。我会把每一步的意图、版本选择的逻辑、以及我实际踩过的坑都摊开讲。
先明确这套组合的定位:
| 组件 | 版本 | 作用 | 关键约束 |
|---|---|---|---|
| CUDA | 10.2 | GPU 通用计算平台 | 决定驱动最低版本 |
| cuDNN | 8.x | 深度神经网络加速库 | 必须匹配 CUDA 10.2 |
| TensorRT | 6.0 | 推理优化引擎 | 必须匹配 CUDA 10.2 + cuDNN 8 |
这三者的关系可以这样理解:CUDA 是地基,cuDNN 是承重墙,TensorRT 是精装修。地基没打好,后面全白搭。而 Ubuntu 18.04 自带的 GCC 7.5 和这套 CUDA 10.2 是兼容的,这也是为什么很多人宁愿守着 18.04 不升级——新系统默认 GCC 版本太高,反而要额外降级,徒增麻烦。
提示:如果你只是想在 Ubuntu 18.04 上跑一个普通的 PyTorch 训练任务,其实没必要上 TensorRT。TensorRT 的价值在推理阶段,尤其是需要低延迟、高吞吐的生产环境。别为了"装而装"。
2. 装之前必须搞清楚的版本对应与驱动底线
2.1 驱动版本决定了你能不能装 CUDA 10.2
很多人一上来就apt install cuda,结果装完nvidia-smi报错,或者 CUDA 跑不起来。根因几乎都是驱动版本不匹配。CUDA 10.2 要求 NVIDIA 驱动版本不低于440.33。你可以先用一条命令确认当前状态:
nvidia-smi看右上角的Driver Version。如果低于 440,要么升级驱动,要么直接装 CUDA 时勾选自带驱动(但自带驱动往往偏旧,不推荐)。我的习惯是先把驱动单独装好,再装 CUDA,这样出问题好定位。
驱动安装有两条路:一是用 Ubuntu 的apt源里的nvidia-driver-440,二是用官方.run文件。前者省心,后者可控。对于 Ubuntu 18.04,我更推荐走 apt:
sudo apt update sudo apt install nvidia-driver-440 sudo reboot重启后再nvidia-smi,能看到显卡信息和驱动版本就说明驱动 OK 了。
2.2 为什么 cuDNN 一定要选 8.x 而不是 7.x
这里有个容易混淆的点。CUDA 10.2 其实同时支持 cuDNN 7.6.x 和 cuDNN 8.x,但TensorRT 6.0 明确要求 cuDNN 8。如果你先装了 cuDNN 7,再装 TensorRT 6.0,编译或运行时会报找不到cudnn*_v8符号的错误。所以顺序上,cuDNN 必须选 8.x 版本,且要选对应 CUDA 10.2 的构建。
cuDNN 8 对应 CUDA 10.2 的包名一般长这样:cudnn-10.2-linux-x64-v8.0.x.xx.tgz。下载下来是个压缩包,里面是头文件和库文件,需要手动拷贝到 CUDA 目录。这一步没有安装脚本,纯手工,所以路径千万别搞错。
2.3 TensorRT 6.0 的包结构要提前看懂
TensorRT 6.0 的 tar 包解压后通常包含这几个目录:bin、include、lib、data、python。其中lib里既有运行时库也有开发库,python目录里是 Python 绑定。很多人装完发现import tensorrt失败,就是因为没处理python目录里的 wheel 包。这个后面会细讲。
版本对应关系我整理成一张表,装之前对着核一遍:
| 组件 | 推荐版本 | 校验方式 |
|---|---|---|
| NVIDIA 驱动 | >= 440.33 | nvidia-smi |
| CUDA | 10.2 | nvcc --version |
| cuDNN | 8.0.x | cat /usr/local/cuda/include/cudnn_version.h |
| TensorRT | 6.0.x | `dpkg -l |
3. CUDA 10.2 的安装:runfile 与 deb 的取舍
3.1 两种安装方式的真实差异
CUDA 10.2 官方提供两种安装包:.run(runfile)和.deb(本地仓库)。我两种都用过,说下实际感受。
.deb方式的好处是走系统包管理,卸载干净,apt remove就能清掉。坏处是它会自动帮你处理依赖,有时候会顺带升级一些系统库,在锁死环境的机器上可能引发连锁反应。.run方式的好处是可控,你可以选择不装驱动、不装 samples,只装 toolkit。坏处是卸载麻烦,得手动删目录。
对于 Ubuntu 18.04 这种老系统,我一般推荐.run方式,因为可控性更重要。但如果你对系统环境不熟,.deb更稳妥。
3.2 runfile 安装的完整操作与关键选项
下载cuda_10.2.89_440.33.01_linux.run之后,先给它执行权限:
chmod +x cuda_10.2.89_440.33.01_linux.run sudo ./cuda_10.2.89_440.33.01_linux.run进入安装界面后,有几个选项必须注意:
- Driver:如果你已经单独装好了 440 驱动,这里取消勾选,否则会覆盖你现有的驱动,可能把图形界面搞崩。
- CUDA Toolkit 10.2:勾选。
- CUDA Samples:可选,建议勾上,后面验证用得上。
- CUDA Toolkit 10.2 的安装路径:默认
/usr/local/cuda-10.2,别改。
安装完成后,需要配置环境变量。编辑~/.bashrc:
export PATH=/usr/local/cuda-10.2/bin:$PATH export LD_LIBRARY_PATH=/usr/local/cuda-10.2/lib64:$LD_LIBRARY_PATH然后source ~/.bashrc,用nvcc --version验证。如果输出Cuda compilation tools, release 10.2,说明 CUDA 装好了。
3.3 一个容易被忽略的软链接问题
/usr/local/cuda这个软链接默认会指向你最后安装的 CUDA 版本。如果你机器上之前装过别的 CUDA,这个链接可能指向旧版本,导致编译时找错头文件。装完 CUDA 10.2 后,手动确认一下:
ls -l /usr/local/cuda如果指向的不是cuda-10.2,就重建:
sudo rm /usr/local/cuda sudo ln -s /usr/local/cuda-10.2 /usr/local/cuda这个坑我在一台装过 CUDA 9 的机器上踩过,编译 TensorRT 示例时一直报头文件版本冲突,查了半天才发现是软链接指错了。
4. cuDNN 8 的手工部署与版本校验
4.1 拷贝文件时的路径陷阱
cuDNN 8 的 tar 包解压后是cuda目录,里面有include和lib64。标准做法是把它们拷到 CUDA 安装目录:
tar -xzvf cudnn-10.2-linux-x64-v8.0.5.39.tgz sudo cp cuda/include/cudnn*.h /usr/local/cuda-10.2/include sudo cp cuda/lib64/libcudnn* /usr/local/cuda-10.2/lib64 sudo chmod a+r /usr/local/cuda-10.2/include/cudnn*.h sudo chmod a+r /usr/local/cuda-10.2/lib64/libcudnn*这里有个细节:cuDNN 8 的头文件从cudnn.h变成了cudnn_version.h和cudnn.h两个。如果你只拷了cudnn.h,编译时可能找不到版本宏。所以拷贝时用通配符cudnn*.h最保险。
4.2 验证 cuDNN 是否真正生效
拷完之后别急着往下走,先验证。最直接的方法是看版本宏:
cat /usr/local/cuda-10.2/include/cudnn_version.h | grep CUDNN_MAJOR -A 2正常应该输出CUDNN_MAJOR 8、CUDNN_MINOR 0之类。如果这个文件不存在,说明你拷的是 cuDNN 7 的包,回去重新下。
另一个验证方式是编译 CUDA samples 里的mnistCUDNN,但这个比较耗时。我一般用头文件校验就够了,快且准。
注意:cuDNN 的库文件权限一定要设成可读,否则非 root 用户跑程序时会报
cannot open shared object file。这个错误信息很有迷惑性,看起来像路径问题,其实是权限问题。
5. TensorRT 6.0 的落地:库、头文件与 Python 绑定
5.1 tar 包解压后的目录该怎么用
TensorRT 6.0 的 tar 包解压后,我建议先放到一个固定位置,比如/opt/TensorRT-6.0.1.5。然后配置环境变量:
export LD_LIBRARY_PATH=/opt/TensorRT-6.0.1.5/lib:$LD_LIBRARY_PATH export PATH=/opt/TensorRT-6.0.1.5/bin:$PATH注意这里不需要把头文件和库拷到 CUDA 目录,TensorRT 是独立的一套。很多人习惯性地往 CUDA 目录里拷,反而造成版本混乱。
5.2 Python 绑定的安装有个大坑
TensorRT 6.0 的python目录里有对应 Python 版本的 wheel 包,比如tensorrt-6.0.1.5-cp36-none-linux_x86_64.whl。Ubuntu 18.04 默认 Python 是 3.6,所以直接:
cd /opt/TensorRT-6.0.1.5/python pip3 install tensorrt-6.0.1.5-cp36-none-linux_x86_64.whl但这里有个坑:这个 wheel 包只装了tensorrt模块,uff和graphsurgeon是分开的。如果你要用 TensorRT 的 Python API 做模型转换,还得装另外两个:
pip3 install uff-0.6.9-py2.py3-none-any.whl pip3 install graphsurgeon-0.4.5-py2.py3-none-any.whl这三个包版本要对应,装错一个,import tensorrt时可能报ImportError。我见过有人只装了 tensorrt,然后跑示例脚本时一直报No module named uff,查了半天。
5.3 用 sample_mnist 做端到端验证
TensorRT 自带sample_mnist示例,是验证整套环境是否打通的最好方式。进入samples/python/mnist目录,先下载 MNIST 数据,然后跑:
python3 sample.py如果能看到推理结果输出,说明 CUDA、cuDNN、TensorRT 三者已经协同工作。如果报错,根据错误信息定位:
| 报错信息 | 可能原因 | 排查方向 |
|---|---|---|
libcudnn.so.8 not found | cuDNN 未正确安装 | 检查 lib64 目录和 LD_LIBRARY_PATH |
undefined symbol: cudnn... | cuDNN 版本不匹配 | 确认是 8.x 而非 7.x |
No module named tensorrt | Python 绑定未装 | 检查 wheel 包是否装对 Python 版本 |
CUDA driver version is insufficient | 驱动版本过低 | 升级到 440+ |
6. 那些文档里不会写的踩坑记录
6.1 装完 CUDA 后图形界面进不去
这个坑我踩过两次。原因是.run安装时勾选了 Driver,把系统自带的 nouveau 驱动和 NVIDIA 驱动搞冲突了。解决办法是进恢复模式,卸载重装驱动,然后重装 CUDA 时不勾选 Driver。如果你已经进不去图形界面,可以按 Ctrl+Alt+F2 进 tty,用命令行处理。
预防措施很简单:装 CUDA 前先确认nvidia-smi能正常输出,装的时候坚决不勾 Driver。
6.2 TensorRT 示例编译时找不到 NvInfer.h
TensorRT 的头文件在include目录,编译时需要显式指定。如果你用 CMake,要在CMakeLists.txt里加:
include_directories(/opt/TensorRT-6.0.1.5/include) link_directories(/opt/TensorRT-6.0.1.5/lib)如果直接 g++ 编译,加-I和-L参数。这个错误很常见,但解决起来就是一行配置的事。
6.3 多版本 CUDA 共存时的环境变量污染
有些机器上同时装了 CUDA 10.0 和 10.2,LD_LIBRARY_PATH里如果两个路径都有,运行时可能加载到错误版本的库。我的做法是环境变量里只保留当前要用的版本,其他版本用的时候再临时切换。可以写个小脚本:
#!/bin/bash export CUDA_HOME=/usr/local/cuda-10.2 export PATH=$CUDA_HOME/bin:$PATH export LD_LIBRARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATH用的时候source一下,干净利落。
6.4 磁盘空间不足导致的静默失败
CUDA 10.2 完整安装大概占 3-4 GB,cuDNN 和 TensorRT 加起来 1 GB 左右。如果/usr/local所在分区空间不够,安装过程可能中途失败但不报明显错误。装之前用df -h看一眼,留出至少 10 GB 余量。这个坑比较隐蔽,因为失败后nvcc --version可能还能输出,但实际库文件不全。
7. 环境验证清单与日常维护建议
7.1 一套命令跑完所有验证
装完之后,我习惯用下面这组命令做一次全面体检:
# 驱动 nvidia-smi # CUDA nvcc --version # cuDNN cat /usr/local/cuda-10.2/include/cudnn_version.h | grep CUDNN_MAJOR -A 2 # TensorRT python3 -c "import tensorrt; print(tensorrt.__version__)" # 综合 python3 -c "import tensorrt as trt; print(trt.Logger(trt.Logger.WARNING))"最后一条如果没报错,说明 TensorRT 的 Python 环境完全可用。
7.2 版本锁定后的维护策略
这套环境一旦跑通,我的建议是不要轻易动。具体做法:
- 把
~/.bashrc里的环境变量备份一份,重装系统时直接恢复。 - 把 CUDA、cuDNN、TensorRT 的安装包留在本地,别删,以后重装省得重新下载。
- 如果要用 Docker,把整套环境打成镜像,比在宿主机上反复折腾靠谱得多。
TensorRT 6.0 的 Docker 镜像官方也有提供,但如果你需要定制,自己写 Dockerfile 更灵活。基础镜像选nvidia/cuda:10.2-cudnn8-devel-ubuntu18.04,然后在里面装 TensorRT,这样版本对应关系天然就是对的。
7.3 关于是否值得升级的个人看法
经常有人问,这套老环境要不要升级到 CUDA 11 + TensorRT 8。我的看法是:如果现有服务稳定运行,没有性能瓶颈,就别升。升级意味着重新验证所有算子、重新测试精度、重新压测性能,成本远高于收益。只有当新版本带来你确实需要的特性(比如新的量化方式、新的算子支持),才值得动。
我在一台边缘设备上守着 CUDA 10.2 跑了两年多,期间只打过一次安全补丁,稳定性比追新强得多。老版本不是技术债,在特定场景下它是经过验证的可靠资产。
最后分享一个实用小技巧:如果你不确定某个 TensorRT 版本支持哪些算子,可以直接看lib目录下的libnvinfer.so符号表,用nm -D过滤一下,比翻文档快。这个习惯帮我省了不少查文档的时间。