课程导入:学习目标、课程结构与环境准备
欢迎来到《CUDA与TensorRT入门知识框架》的第一章。本章是整个课程的地基,我们将明确三个核心问题:学完这门课你能做什么、课程如何组织,以及如何搭建可用的开发环境。CUDA是NVIDIA GPU的通用并行计算平台,TensorRT则是基于CUDA的高性能推理优化引擎。理解两者的关系,是后续所有实践的前提。
1.1 学习目标:从“能跑”到“会优化”
本课程不追求面面俱到的理论推导,而是聚焦于工程落地中最常用的知识链路。完成本课程后,你应该具备以下能力:
- 理解GPU异构计算模型:清楚Host(CPU)与Device(GPU)的分工,掌握线程层次结构(Grid、Block、Thread)与内存层次结构(全局内存、共享内存、寄存器)。
- 编写并调试CUDA程序:能够使用nvcc编译、运行简单的kernel,并利用cuda-memcheck或compute-sanitizer排查越界与同步错误。
- 掌握TensorRT优化流程:能够将训练好的PyTorch/ONNX模型转换为TensorRT引擎,理解精度校准(FP16/INT8)与动态形状(Dynamic Shape)的配置方法。
- 具备性能分析意识:会使用Nsight Systems与Nsight Compute定位瓶颈,区分“访存密集”与“计算密集”算子,并据此选择优化策略。
1.2 课程结构:四阶段递进式设计
整个课程共30章,分为四个阶段。每个阶段都有明确的交付物,避免“学完就忘”。
| 阶段 | 章节范围 | 核心主题 | 阶段产出 |
|---|---|---|---|
| 基础入门 | 第1-8章 | CUDA编程模型、内存管理、线程同步 | 手写向量加法、矩阵乘法kernel |
| 性能优化 | 第9-15章 | 访存优化、占用率调优、算子融合 | GEMM性能达到cuBLAS的60%以上 |
| 推理部署 | 第16-24章 | TensorRT API、ONNX解析、INT8量化 | YOLOv5模型TensorRT加速部署 |
| 工程实战 | 第25-30章 | 多流并发、TensorRT-LLM、性能剖析 | 高并发推理服务端Demo |
这种结构遵循“原理→实践→优化→部署”的认知路径。前8章如果基础不牢,后续的优化章节会非常吃力,尤其是共享内存的bank conflict问题,需要反复动手实验才能理解。
1.3 环境准备:CUDA与TensorRT安装
环境搭建是初学者最容易受挫的环节。这里我们采用“驱动→CUDA Toolkit→cuDNN→TensorRT”的安装顺序,每一步都验证后再进入下一步。
1.3.1 检查GPU与驱动
首先确认GPU型号与驱动版本。在Linux终端执行:
nvidia-smi
# 输出示例:
# +-----------------------------------------------------------------------------+
# | NVIDIA-SMI 525.85.12 Driver Version: 525.85.12 CUDA Version: 12.0 |
# |-------------------------------+----------------------+----------------------+
# | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
# | 0 NVIDIA GeForce RTX 4090 | On | N/A |
# +-------------------------------+----------------------+----------------------+
注意右上角的CUDA Version是驱动支持的最高CUDA版本,并不代表已安装CUDA Toolkit。驱动版本必须≥450.80.02(CUDA 11.0的最低要求),推荐使用最新稳定版驱动。
1.3.2 安装CUDA Toolkit
CUDA Toolkit包含编译器nvcc、运行时库和开发工具。推荐使用runfile(本地安装包)方式,便于自定义安装路径。以CUDA 12.1为例:
wget https://developer.download.nvidia.com/compute/cuda/12.1.1/local_installers/cuda_12.1.1_530.30.02_linux.run
sudo sh cuda_12.1.1_530.30.02_linux.run
# 安装时取消勾选Driver(因为已安装),只保留Toolkit和Samples
安装完成后,设置环境变量。在~/.bashrc末尾添加:
export PATH=/usr/local/cuda-12.1/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda-12.1/lib64:$LD_LIBRARY_PATH
验证安装:
nvcc --version
# 输出应包含 "Cuda compilation tools, release 12.1, V12.1.105"
sudo apt install nvidia-cuda-toolkit安装,Ubuntu仓库中的版本通常较旧,且与TensorRT的兼容性难以保证。务必从NVIDIA官网下载对应版本的runfile。
1.3.3 安装cuDNN与TensorRT
cuDNN是深度神经网络的加速库,TensorRT依赖它进行卷积等算子的底层优化。下载cuDNN需要NVIDIA开发者账号,选择与CUDA 12.1匹配的版本(如cuDNN 8.9.x)。安装步骤:
# 解压后复制到CUDA目录
tar -xvf cudnn-linux-x86_64-8.9.2.26_cuda12-archive.tar.xz
sudo cp cudnn-*-archive/include/cudnn*.h /usr/local/cuda-12.1/include/
sudo cp -P cudnn-*-archive/lib/libcudnn* /usr/local/cuda-12.1/lib64/
sudo chmod a+r /usr/local/cuda-12.1/lib64/libcudnn*
TensorRT的安装推荐使用tar包方式,便于管理版本。以TensorRT 8.6.1为例:
tar -xzvf TensorRT-8.6.1.6.Linux.x86_64-gnu.cuda-12.0.tar.gz
# 将路径加入环境变量
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/TensorRT-8.6.1.6/lib
验证TensorRT是否可用,运行Python测试:
python3 -c "import tensorrt as trt; print(trt.__version__)"
# 输出应为 8.6.1
1.4 核心原理:CUDA与TensorRT的分工
为了后续章节的展开,这里必须厘清两个关键概念。CUDA是通用并行计算平台,它允许你直接编写GPU kernel,控制线程调度与内存布局。而TensorRT是推理优化引擎,它读取训练好的模型,通过层融合、精度校准、内核自动调优等手段,生成一个针对特定GPU和输入尺寸高度优化的推理引擎。
下图展示了从模型到部署的完整链路,以及CUDA与TensorRT在其中的位置:
从图中可以看到,TensorRT位于ONNX与推理服务之间,它输出的.engine文件是经过优化的、与具体GPU绑定的二进制序列化引擎。而CUDA作为最底层的平台,为TensorRT提供运行时支撑。理解这条链路,你就明白了为什么安装顺序必须是“驱动→CUDA→cuDNN→TensorRT”——每一层都依赖下一层的API。
1.5 案例:一个最小可运行的CUDA程序
为了验证环境是否真正可用,我们编写一个经典的向量加法程序。创建vector_add.cu:
#include <stdio.h>
__global__ void vecAdd(float *a, float *b, float *c, int n) {
int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i < n) {
c[i] = a[i] + b[i];
}
}
int main() {
int n = 1024;
size_t bytes = n * sizeof(float);
float *h_a, *h_b, *h_c;
float *d_a, *d_b, *d_c;
// 分配主机内存
h_a = (float*)malloc(bytes);
h_b = (float*)malloc(bytes);
h_c = (float*)malloc(bytes);
// 初始化数据
for (int i = 0; i < n; i++) {
h_a[i] = 1.0f;
h_b[i] = 2.0f;
}
// 分配设备内存
cudaMalloc(&d_a, bytes);
cudaMalloc(&d_b, bytes);
cudaMalloc(&d_c, bytes);
// 拷贝数据到设备
cudaMemcpy(d_a, h_a, bytes, cudaMemcpyHostToDevice);
cudaMemcpy(d_b, h_b, bytes, cudaMemcpyHostToDevice);
// 启动kernel:256线程/块,共4块
vecAdd<<<4, 256>>>(d_a, d_b, d_c, n);
// 拷贝结果回主机
cudaMemcpy(h_c, d_c, bytes, cudaMemcpyDeviceToHost);
// 验证结果
for (int i = 0; i < 10; i++) {
printf("c[%d] = %f\n", i, h_c[i]);
}
// 释放内存
cudaFree(d_a); cudaFree(d_b); cudaFree(d_c);
free(h_a); free(h_b); free(h_c);
return 0;
}
编译并运行:
nvcc -o vector_add vector_add.cu
./vector_add
# 预期输出:c[0] = 3.000000, c[1] = 3.000000, ...
如果程序输出正确,说明CUDA环境完全可用。这里<<<4, 256>>>表示启动4个Block,每个Block有256个Thread,总共1024个线程,恰好对应数组长度。
1.6 误区与复盘:环境搭建的常见陷阱
根据过往学员的反馈,以下三个问题出现频率最高,值得提前规避:
libnvinfer.so,如果未将TensorRT的lib目录加入环境变量,会出现ImportError: libnvinfer.so.8: cannot open shared object file。每次新开终端都需要重新export,建议写入~/.bashrc。