第一章:CUDA简介与环境搭建
GPU计算概述——为什么我们需要它?
说实话,我第一次接触GPU计算时,心里也犯嘀咕:CPU不是挺好的吗?干嘛非要折腾GPU?
后来我在一个图像处理项目里被现实狠狠教育了一回。一张4K图片的像素点有800多万个,用CPU逐个处理,那速度简直让人抓狂。你想想看,CPU就像一辆法拉利,跑得飞快,但它一次只能拉一个人。而GPU呢?它像一辆大巴车,速度没那么夸张,但一次能拉几百号人。
这就是GPU计算的核心思想——并行计算。CPU擅长处理复杂的逻辑任务,GPU则擅长处理大量相同类型的简单运算。说白了,就是「人多力量大」。
核心概念:GPU计算(GPGPU,General-Purpose computing on Graphics Processing Units)就是利用GPU强大的并行计算能力,去解决原本由CPU处理的通用计算问题。它特别适合数据并行、计算密集型的任务。
我习惯把GPU计算的应用场景分成三类:
- 图像与视频处理:滤波、变换、编解码——每个像素独立运算,天然适合并行
- 科学计算与仿真:分子动力学、气象预报、流体力学——计算量大到CPU扛不住
- 深度学习:矩阵乘法、卷积操作——这几乎是GPU的「主场」
CUDA架构——NVIDIA的「秘密武器」
CUDA是NVIDIA在2007年推出的并行计算平台和编程模型。我记得当时业内一片哗然——终于有人把GPU的「黑盒」打开了,让开发者可以直接用C语言写GPU程序。
CUDA架构有几个关键概念,我建议你牢牢记住:
| 概念 | 说明 | 我的理解 |
|---|---|---|
| Host | CPU及其内存系统 | 负责控制、调度、逻辑判断 |
| Device | GPU及其显存系统 | 负责大规模并行计算 |
| Kernel | 在GPU上执行的函数 | 用__global__修饰,由CPU调用 |
| Thread | 最小的执行单元 | 每个线程执行同一个kernel |
| Block | 线程的集合 | 同一block内的线程可以共享内存 |
| Grid | block的集合 | 一个kernel对应一个grid |
你可能会问:为什么要搞这么多层级?
嗯,这里有个关键点。GPU里有成百上千个计算核心,如果让开发者直接管理每个核心,那代码会变得极其复杂。CUDA通过「线程-块-网格」这种分层结构,把并行度管理的复杂性封装了起来。你只需要告诉CUDA「我要启动多少个线程」,剩下的硬件调度由它自动完成。
我的经验:刚开始学CUDA时,我总纠结于block和thread的具体数量。后来发现,先跑通再优化才是正道。默认用256个线程一个block,基本不会出大问题。
CUDA Toolkit安装——手把手教你配环境
安装CUDA Toolkit,说白了就是三步:下载、安装、配置环境变量。但我在项目中遇到过不少坑,这里给你列个避坑指南。
第一步:确认硬件兼容性
先看看你的NVIDIA显卡支不支持CUDA。在命令行里敲:
nvidia-smi
如果能看到显卡型号和驱动版本,恭喜你,硬件没问题。如果提示「命令未找到」,那就先去NVIDIA官网装驱动。
我曾经踩过的坑:有一次我直接在Ubuntu的软件源里装驱动,结果装完系统直接黑屏。后来学乖了,老老实实去NVIDIA官网下载.run文件手动安装。记住:永远不要用系统自带的驱动管理器装NVIDIA驱动。
第二步:下载并安装CUDA Toolkit
去NVIDIA开发者官网(developer.nvidia.com/cuda-downloads),选择你的操作系统和安装方式。我个人习惯用.run文件安装,因为可控性更强。
以Ubuntu 22.04为例:
wget https://developer.download.nvidia.com/compute/cuda/12.1.0/local_installers/cuda_12.1.0_530.30.02_linux.run
sudo sh cuda_12.1.0_530.30.02_linux.run
安装过程中会问你是否安装驱动——如果你已经装好了,就取消勾选「Driver」选项,只装Toolkit。
第三步:配置环境变量
安装完成后,把CUDA的bin和lib64目录加到PATH和LD_LIBRARY_PATH里。编辑~/.bashrc,在末尾加上:
export PATH=/usr/local/cuda-12.1/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda-12.1/lib64:$LD_LIBRARY_PATH
然后source ~/.bashrc让它生效。验证一下:
nvcc --version
如果看到版本号,说明安装成功了。
小技巧:我习惯在/usr/local下创建一个软链接cuda指向当前版本,这样以后升级CUDA时,只需要改软链接,不用改环境变量。
nvcc编译器——CUDA程序的「翻译官」
nvcc是CUDA的编译器,它负责把.cu文件编译成可执行文件。你想想看,一个.cu文件里既有CPU代码(C++),又有GPU代码(CUDA C),nvcc需要把它们分开处理:
- GPU代码 → 编译成PTX(并行线程执行)中间代码 → 再编译成cubin二进制
- CPU代码 → 交给系统自带的C++编译器(如g++)处理
一个最简单的编译命令:
nvcc -o hello hello.cu
常用的编译选项我整理了一下:
| 选项 | 作用 | 我常用的场景 |
|---|---|---|
-arch=sm_86 |
指定GPU架构(如RTX 30系列是sm_86) | 编译针对特定显卡优化的代码 |
-O2 |
优化等级 | 发布版本必加 |
-G |
生成调试信息 | 调试阶段使用,但会降低性能 |
-lineinfo |
保留行号信息 | 配合profiler分析性能时用 |
注意:如果你用-arch=sm_86编译的程序,放到GTX 1080(sm_61)上跑,会直接报错。我建议编译时用-arch=sm_61这种较低的版本号,兼容性更好。或者用-gencode选项生成多个架构的fatbin。
本章知识体系
下面这张图帮你理清本章的核心脉络:
这张图把本章的四个核心模块串在了一起。从「为什么需要GPU计算」开始,到「CUDA架构」理解工作原理,再到「环境搭建」和「编译器使用」——每一步都是后续章节的基石。
我个人觉得,环境搭建这一步虽然枯燥,但值得认真对待。我见过太多同学卡在「Hello World」跑不通的环节,最后发现是环境变量没配好。嗯,磨刀不误砍柴工,把这一步走稳了,后面会顺畅很多。