2、开发环境搭建:CUDA与cuDNN安装、TensorRT安装、CMake工程配置、验证环境

好,咱们直接进入正题。开发环境搭建这事儿,说难不难,说简单吧,坑还真不少。我见过太多同学卡在这一步,一卡就是好几天。其实说白了,就是版本匹配的问题。你想想看,CUDA、cuDNN、TensorRT这三个东西,版本不对付,编译就报错,跑起来就崩溃。

我个人习惯是,先定好TensorRT的版本,再倒推CUDA和cuDNN的版本。为什么?因为TensorRT对CUDA版本有硬性要求,你装了个最新的CUDA 12.x,结果TensorRT 8.x不支持,那就尴尬了。

2.1 CUDA与cuDNN安装

先讲CUDA。我建议你用runfile方式安装,别用deb包。deb包虽然方便,但会把驱动也一起装了,万一你机器上有NVIDIA驱动,容易冲突。runfile方式只装CUDA Toolkit,驱动单独管理。

下载地址我就不贴了,直接去NVIDIA官网找CUDA Toolkit Archive。选版本的时候注意,TensorRT 8.5对应CUDA 11.8,TensorRT 8.6对应CUDA 12.0,这个对应关系一定要查清楚。

我的经验:CUDA安装完后,一定要检查/usr/local/cuda这个软链接是否指向了你安装的版本。我遇到过好几次,系统里装了多个CUDA版本,软链接指错了,编译时死活找不到库。

安装命令很简单:

# 下载runfile
wget https://developer.download.nvidia.com/compute/cuda/11.8.0/local_installers/cuda_11.8.0_520.61.05_linux.run

# 执行安装,注意不要选Driver
sudo sh cuda_11.8.0_520.61.05_linux.run

# 配置环境变量
echo 'export PATH=/usr/local/cuda/bin:$PATH' >> ~/.bashrc
echo 'export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH' >> ~/.bashrc
source ~/.bashrc

接下来是cuDNN。cuDNN其实就是一堆库文件,下载后解压,把文件拷贝到CUDA目录下就行。

# 下载cuDNN(需要注册NVIDIA账号)
# 解压
tar -xzvf cudnn-linux-x86_64-8.9.0.131_cuda11-archive.tar.xz

# 拷贝文件
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的版本号要和CUDA匹配。比如cuDNN 8.9 for CUDA 11.x,就不能用在CUDA 12.x上。我曾经有一次没注意,把cuDNN 8.9 for CUDA 12.x装到了CUDA 11.8上,结果训练时直接报错,排查了半天。

2.2 TensorRT安装

TensorRT的安装方式有两种:tar包和deb包。我推荐用tar包,因为灵活,可以随时切换版本。deb包会安装到系统目录,想换版本还得卸载,麻烦。

下载TensorRT时,注意选择对应CUDA版本的包。文件名里会标明,比如TensorRT-8.5.3.1.Linux.x86_64-gnu.cuda-11.8.cudnn8.6.tar.gz,这个就是给CUDA 11.8用的。

# 解压
tar -xzvf TensorRT-8.5.3.1.Linux.x86_64-gnu.cuda-11.8.cudnn8.6.tar.gz

# 移动到常用目录
sudo mv TensorRT-8.5.3.1 /usr/local/

# 配置环境变量
echo 'export LD_LIBRARY_PATH=/usr/local/TensorRT-8.5.3.1/lib:$LD_LIBRARY_PATH' >> ~/.bashrc
echo 'export PATH=/usr/local/TensorRT-8.5.3.1/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

安装Python包(如果你要用Python接口的话):

cd /usr/local/TensorRT-8.5.3.1/python
pip install tensorrt-8.5.3.1-cp38-none-linux_x86_64.whl

小技巧:安装完后,可以用python -c "import tensorrt; print(tensorrt.__version__)"验证Python接口是否正常。如果报错,多半是Python版本不匹配,换个whl文件试试。

2.3 CMake工程配置

好,环境装完了,接下来配置CMake工程。这是写自定义插件的基础,工程搭不好,后面写代码全是坑。

先看一个标准的CMakeLists.txt:

cmake_minimum_required(VERSION 3.10)
project(MyTensorRTPlugin)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 查找CUDA
find_package(CUDA REQUIRED)

# 设置TensorRT路径
set(TENSORRT_ROOT "/usr/local/TensorRT-8.5.3.1")
set(TENSORRT_INCLUDE_DIR "${TENSORRT_ROOT}/include")
set(TENSORRT_LIB_DIR "${TENSORRT_ROOT}/lib")

# 包含头文件
include_directories(
    ${CUDA_INCLUDE_DIRS}
    ${TENSORRT_INCLUDE_DIR}
)

# 添加自定义插件源文件
cuda_add_library(my_plugin SHARED
    src/my_plugin.cpp
    src/my_plugin_kernel.cu
)

# 链接库
target_link_libraries(my_plugin
    ${CUDA_LIBRARIES}
    ${TENSORRT_LIB_DIR}/libnvinfer.so
    ${TENSORRT_LIB_DIR}/libnvinfer_plugin.so
)

这里有几个关键点:

  • find_package(CUDA REQUIRED)会自动找到CUDA路径,前提是你配好了环境变量
  • cuda_add_library是CUDA提供的宏,会自动处理.cu文件的编译
  • 链接libnvinfer.solibnvinfer_plugin.so,这是TensorRT的核心库和插件库

避坑指南:我曾经在CMake里直接写target_link_libraries(my_plugin nvinfer),结果编译过了,运行时却报undefined symbol。后来发现是没指定库的完整路径,系统找到了一个旧版本的libnvinfer.so。所以,老老实实写全路径,别偷懒。

2.4 验证环境

环境搭没搭好,跑个demo就知道了。我写了个简单的验证脚本,检查CUDA、cuDNN、TensorRT是否都能正常工作。

// test_env.cu
#include <iostream>
#include <cuda_runtime.h>
#include <cudnn.h>
#include <NvInfer.h>

int main() {
    // 验证CUDA
    int deviceCount;
    cudaGetDeviceCount(&deviceCount);
    std::cout << "CUDA devices: " << deviceCount << std::endl;

    // 验证cuDNN
    cudnnHandle_t cudnn;
    cudnnCreate(&cudnn);
    std::cout << "cuDNN initialized successfully" << std::endl;
    cudnnDestroy(cudnn);

    // 验证TensorRT
    nvinfer1::IBuilder* builder = nvinfer1::createInferBuilder(nullptr);
    std::cout << "TensorRT version: " << NV_TENSORRT_VERSION << std::endl;
    builder->destroy();

    return 0;
}

编译命令:

nvcc test_env.cu -o test_env -I/usr/local/cuda/include -I/usr/local/TensorRT-8.5.3.1/include -L/usr/local/TensorRT-8.5.3.1/lib -lnvinfer -lcudart -lcudnn

./test_env

如果输出类似下面这样,说明环境没问题:

CUDA devices: 1
cuDNN initialized successfully
TensorRT version: 8503

注意:如果运行时提示cannot open shared object file,说明动态库路径没配好。检查一下LD_LIBRARY_PATH是否包含了TensorRT和CUDA的lib目录。我建议直接在/etc/ld.so.conf.d/下创建一个配置文件,一劳永逸。

嗯,到这里环境就搭好了。说实话,这一步是最磨人的,但也是最重要的。环境搭好了,后面写插件就是水到渠成的事。下一章我们开始写第一个自定义插件,到时候你就知道今天花的时间值不值了。