第二章 环境准备:操作系统选型、NVIDIA驱动安装、CUDA Toolkit安装、cuDNN安装、环境验证
好,咱们直接进入正题。环境准备这事儿,说简单也简单,说复杂能让你折腾一整天。我见过太多人在这一步翻车了——驱动版本不对、CUDA和cuDNN不匹配、装完跑不起来。嗯,咱们今天就把这事彻底捋清楚。
2.1 操作系统选型
我个人习惯用Ubuntu Server 20.04 LTS或22.04 LTS。为什么?因为NVIDIA的官方文档、社区踩坑记录,基本都是基于Ubuntu的。你非要用CentOS或Rocky Linux?也不是不行,但你会多花不少时间在解决依赖问题上。
核心建议:新手直接选Ubuntu 22.04 LTS。老手随意,但别在操作系统上搞特殊化。
这里有个小细节:安装时记得选「SSH server」和「最小化安装」。GPU集群的节点通常没有显示器,你全靠SSH连进去。图形界面?那是浪费显存的东西。
我的经验:我曾经在一台机器上装了带GUI的Ubuntu,结果发现Xorg占用了200MB显存。对于训练任务来说,这200MB可能就是batch size从32降到28的差距。
2.2 NVIDIA驱动安装
驱动安装是第一个坑。很多人直接去NVIDIA官网下载.run文件,然后sh一下完事。我建议你别这么干——用包管理器安装更稳妥。
先看看你的显卡型号:
lspci | grep -i nvidia
然后添加NVIDIA的官方仓库:
# 添加驱动PPA
sudo add-apt-repository ppa:graphics-drivers/ppa
sudo apt update
# 查看可用驱动版本
ubuntu-drivers devices
# 安装推荐版本
sudo ubuntu-drivers autoinstall
装完重启,用nvidia-smi验证。如果看到类似下面的输出,说明驱动装好了:
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 535.129.03 Driver Version: 535.129.03 CUDA Version: 12.2 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
|===============================+======================+======================|
| 0 NVIDIA A100-SXM4-80GB On | 00000000:00:04.0 Off | 0 |
+-------------------------------+----------------------+----------------------+
注意:千万别装Nouveau开源驱动!它和NVIDIA闭源驱动冲突。如果你发现nvidia-smi报错,先检查是不是Nouveau在作怪:lsmod | grep nouveau。有输出的话,把它加入黑名单。
2.3 CUDA Toolkit安装
驱动装好了,接下来是CUDA Toolkit。这里有个很多人搞混的概念:驱动里自带的CUDA版本,和你安装的CUDA Toolkit版本,是两回事。
驱动里的CUDA版本,决定了你的GPU能支持到什么算力。而CUDA Toolkit是你编译代码时用的开发工具包。说白了,驱动是「运行时」,Toolkit是「开发时」。
我建议用runfile方式安装,这样你可以自由切换版本:
# 下载CUDA 12.2 runfile
wget https://developer.download.nvidia.com/compute/cuda/12.2.0/local_installers/cuda_12.2.0_535.54.03_linux.run
# 执行安装(注意:不要安装驱动!)
sudo sh cuda_12.2.0_535.54.03_linux.run --toolkit --silent --override
装完后配置环境变量:
echo 'export PATH=/usr/local/cuda-12.2/bin:$PATH' >> ~/.bashrc
echo 'export LD_LIBRARY_PATH=/usr/local/cuda-12.2/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc
source ~/.bashrc
避坑指南:我曾经在集群上同时装了CUDA 11.8和12.2,结果发现有些旧代码只支持11.x。我的做法是用软链接切换默认版本:sudo ln -sf /usr/local/cuda-11.8 /usr/local/cuda。这样你只需要改一个链接,所有环境变量都不用动。
2.4 cuDNN安装
cuDNN是NVIDIA的深度学习加速库。没有它,你的卷积、池化、LSTM这些操作会慢一个数量级。
安装cuDNN需要NVIDIA开发者账号。下载后是个tar包:
# 解压
tar -xzvf cudnn-linux-x86_64-8.9.4.25_cuda12-archive.tar.xz
# 复制到CUDA目录
sudo cp cudnn-*-archive/include/cudnn*.h /usr/local/cuda/include
sudo cp -P cudnn-*-archive/lib/libcudnn* /usr/local/cuda/lib64
sudo chmod a+r /usr/local/cuda/include/cudnn*.h /usr/local/cuda/lib64/libcudnn*
验证cuDNN版本:
cat /usr/local/cuda/include/cudnn_version.h | grep CUDNN_MAJOR -A 2
输出应该类似:
#define CUDNN_MAJOR 8
#define CUDNN_MINOR 9
#define CUDNN_PATCHLEVEL 4
重要:cuDNN版本必须和CUDA版本匹配。比如CUDA 12.2对应cuDNN 8.9.x。你非要用cuDNN 8.4配CUDA 12.2?嗯,编译会报一堆undefined reference错误,别问我怎么知道的。
2.5 环境验证
所有东西装完了,咱们得跑个测试验证一下。我习惯写一个简单的CUDA程序:
// test.cu
#include <stdio.h>
#include <cuda_runtime.h>
int main() {
int deviceCount;
cudaGetDeviceCount(&deviceCount);
printf("检测到 %d 个GPU设备\n", deviceCount);
for (int i = 0; i < deviceCount; i++) {
cudaDeviceProp prop;
cudaGetDeviceProperties(&prop, i);
printf("设备 %d: %s\n", i, prop.name);
printf(" 计算能力: %d.%d\n", prop.major, prop.minor);
printf(" 显存大小: %.2f GB\n", prop.totalGlobalMem / 1024.0 / 1024.0 / 1024.0);
}
return 0;
}
编译运行:
nvcc test.cu -o test
./test
如果看到正确的GPU信息,恭喜你,环境搞定了。
再跑一个cuDNN的测试:
# 编译cuDNN示例
cp -r /usr/src/cudnn_samples_v8/ ~/
cd ~/cudnn_samples_v8/mnistCUDNN
make clean && make
./mnistCUDNN
看到「Test passed!」就对了。
完整验证清单:
- ✅ nvidia-smi 显示GPU信息
- ✅ nvcc --version 显示CUDA版本
- ✅ 编译运行test.cu无报错
- ✅ cuDNN示例通过测试
2.6 知识体系总览
下面这张图把整个环境准备流程串起来了。你跟着这个流程走,基本不会出大问题:
整个流程走下来,大概需要30分钟到1小时。第一次装可能会慢点,但熟练之后,你闭着眼睛都能搞定。嗯,环境准备就说到这,接下来你可以放心地开始写你的CUDA代码了。
最后提醒一句:装完环境后,建议做个快照或镜像。万一哪天搞崩了,直接恢复,不用从头再来。我在生产环境上吃过这个亏——一次内核升级把驱动搞挂了,重装花了半天。