第一次在Ubuntu上折腾CUDA Fortran环境时,我对着报错信息折腾了整整三天。后来才发现是系统内核头文件没装对。为了避免大家重蹈覆辙,我把完整的检查流程整理出来。先别急着安装,这些前置检查能帮你避开90%的坑。
打开终端输入lspci | grep -i nvidia,如果看到类似"GeForce RTX 2080 Ti"的输出,说明你的显卡被系统识别了。但被识别不等于支持CUDA,建议去NVIDIA官网查兼容列表。我去年用的一块老Quadro卡就不在CUDA 11的支持列表里,最后只能降级安装CUDA 10。
运行uname -m && cat /etc/*release查看系统架构和版本。重点看两点:一是必须x86_64架构(ARM暂时别想玩CUDA),二是Ubuntu版本。虽然理论上18.04以上都行,但我实测20.04 LTS最稳。曾经在22.04上遇到内核模块签名问题,新手建议避开最新发行版。
输入gcc --version确认gcc是否存在。有趣的是,CUDA对gcc版本有上限要求(比如CUDA 11.1最高支持gcc 9),而PGI编译器又对gcc有下限要求。这个"版本夹心"问题我们后面会专门解决。建议先用sudo apt install build-essential装全开发工具。
执行sudo apt install linux-headers-$(uname -r)安装当前内核对应的头文件。这里有个隐藏坑:如果你刚升级过内核但没重启,uname -r显示的可能不是实际运行的内核版本。我就这样浪费过两小时,所以务必重启后再检查。
很多教程建议分开装驱动和CUDA,其实从CUDA 10开始,用官方runfile一次性安装更省心。不过要注意,这种方式会自动安装驱动,可能会覆盖你现有的驱动版本。
新建文件/etc/modprobe.d/blacklist-nouveau.conf,写入:
bash复制blacklist nouveau
options nouveau modeset=0
然后执行sudo update-initramfs -u并重启。建议用lsmod | grep nouveau二次确认,如果还有输出,可能是拼写错误或者没重启。
到NVIDIA官网下载驱动时,别只看最新版。比如RTX 30系卡用470版驱动会有DPC延迟问题,推荐465或495版。安装命令sudo sh NVIDIA-Linux-x86_64-xxx.xx.run加上--no-opengl-files参数可以避免图形界面冲突。
CUDA 11.x是目前最稳定的选择,但要注意小版本差异。比如11.1对Ampere架构支持不完善,11.4开始要求gcc 10+。下载runfile时建议用国内镜像,官方源速度感人。安装时记得取消勾选自带的驱动,除非你想重装驱动。
在~/.bashrc添加:
bash复制export PATH=/usr/local/cuda/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH
新手常犯的错误是路径写错(比如漏了lib64),或者忘记source ~/.bashrc。可以用nvcc --version验证,如果报错就检查路径中的cuda版本号是否与实际安装一致。
PGI现在叫NVIDIA HPC SDK,安装包从原来的300MB暴涨到2GB。社区版虽然免费,但有线程数限制,做大规模并行计算可能会触发限制。
官网下载需要填邮箱,但实测临时邮箱也能用。下载后务必校验sha256,我遇到过镜像站文件损坏的情况。解压后不要直接sudo install,先用./install查看依赖项,缺什么补什么。
除了常规的PATH设置,PGI还需要特别处理:
bash复制export PGI=/opt/pgi
export MANPATH=$MANPATH:$PGI/linux86-64/20.4/man
export LM_LICENSE_FILE=$PGI/license.dat
如果遇到license报错,试试把系统时间调回安装日期附近。曾经有台服务器因为BIOS电池没电导致时间错误,license校验直接失败。
当系统gcc太新时,可以这样降级:
bash复制sudo apt install gcc-9 g++-9
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 50
比手动下载deb包安全得多。PGI 20.4开始支持gcc 10,但如果要用CUDA Fortran,建议还是保持gcc 9更稳妥。
最后阶段往往最令人崩溃。明明所有组件都装好了,就是跑不起来。这时候需要系统化的验证方法。
进入/usr/local/cuda/samples,执行:
bash复制make -j$(nproc)
./bin/x86_64/linux/release/deviceQuery
如果看到"Result = PASS",至少说明CUDA能识别你的显卡。要是编译失败,大概率是gcc版本或者头文件问题。
用这个简单例子测试:
fortran复制program hello
use cudafor
implicit none
type(dim3) :: grid, block
grid = dim3(1,1,1)
block = dim3(1,1,1)
print *, "CUDA Fortran is working!"
end program
编译命令pgfortran -Mcuda hello.cuf如果报"undefined reference",可能是环境变量没生效或者编译器版本不匹配。
在~/.bashrc添加:
bash复制export PGI_ACC_TIME=1
export PGI_ACC_NOTIFY=1
运行程序时会显示GPU内核执行时间。曾经有个矩阵乘法的例子,通过调整block大小获得了3倍加速。记住:默认参数通常不是最优的,需要根据数据规模反复试验。