1. 下载与查询
下载地址
CUDA:https://developer.nvidia.com/cuda-toolkit-archive
cuDNN:https://developer.nvidia.com/rdp/cudnn-archive
TensorRT:https://developer.nvidia.com/tensorrt-download
Ubuntu系统:Ubuntu 中文站
→
\to
→ 下载
→
\to
→ Ubuntu桌面系统
→
\to
→ 其他下载
→
\to
→ 查看全部Ubuntu镜像站
→
\to
→ 选择China 北大源
→
\to
→ 选择版本
→
\to
→ 下载 ubuntu-20.04.6-desktop-amd64.iso
信息查询 / 验证安装
- 操作系统内核:
uname -a
→ x86_64 - 操作系统版本:
cat /proc/version
→ Ubuntu 20.04.2 - 显卡型号:
lspci | grep -i vga
显卡ID查询:http://pci-ids.ucw.cz/mods/PC/10de?action=help?help=pci - 显卡驱动:
nvidia-smi
- CUDA 版本:
nvcc -V
- cuDNN 版本:
cat /usr/local/cuda/include/cudnn.h | grep CUDNN_MAJOR -A 2
(旧版)
cat /usr/local/cuda/include/cudnn_version.h | grep CUDNN_MAJOR -A 2
(新版)
2. 安装
在下载页面基本都有官方的安装教程链接,安装本身并不复杂,主要需要注意各种版本的选择。
总体来说,先根据硬件条件安装显卡驱动,显卡驱动决定了所能安装的最高 CUDA 版本。根据项目需求等选择 TensorRT 版本,一般会有多个 CUDA 版本与 TensorRT 兼容,只要有一个低于最高版本要求即可。CUDA 版本决定 cuDNN 版本。在 4.1 节中安装 torch-tensorrt
会对 PyTorch 版本有一定要求。建议先把各项版本都确定好再安装,避免踩坑。
2.1 显卡驱动
ubuntu-drivers devices
== /sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0 ==
modalias : pci:v000010DEd00002204sv00001043sd000087D5bc03sc00i00
vendor : NVIDIA Corporation
driver : nvidia-driver-535 - distro non-free
driver : nvidia-driver-470 - distro non-free
driver : nvidia-driver-535-server-open - distro non-free recommended
driver : nvidia-driver-535-server - distro non-free
driver : nvidia-driver-535-open - distro non-free
driver : nvidia-driver-525 - distro non-free
driver : nvidia-driver-470-server - distro non-free
driver : nvidia-driver-525-open - distro non-free
driver : nvidia-driver-525-server - distro non-free
driver : xserver-xorg-video-nouveau - distro free builtin
通常会直接安装推荐的驱动(带 recommended 标记的)。由于硬件原因,此处推荐的是带 server 的版本(服务器版本),如果安装会不支持外接显示器,还是选择装不带 server 的版本。
sudo apt update
sudo apt install nvidia-driver-535
2.2 CUDA
nvidia-smi
表格开头的 CUDA Version: 12.2
代表了可安装 CUDA 的最高版本,cuDNN 和 TensorRT 下载时可看到所支持的 CUDA 版本。此处可具体查询 CUDA 与各项版本的依赖关系。
本文选用的各项版本为:CUDA 11.8、cuDNN 8.9.6.50、TensorRT 8.6.1.6。
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.129.03 Driver Version: 535.129.03 CUDA Version: 12.2 |
|-----------------------------------------+----------------------+----------------------+
下载页面选择 CUDA 版本后,需根据系统情况选择。
例如: Linux → x86_64 → Ubuntu → 20.04 → runfile,页面下方有下载和安装命令:
wget https://developer.download.nvidia.com/compute/cuda/11.8.0/local_installers/cuda_11.8.0_520.61.05_linux.run
sudo sh cuda_11.8.0_520.61.05_linux.run
等待一段时间后会出现安装界面,上下键切换选项(continue → 输入accept → 取消选择 Driver → Install)。TODO:CUDA 安装各种选项区别
安装完成后手动添加环境变量:
export PATH=/usr/local/cuda-11.8/bin${PATH:+:${PATH}}
64-bit system:
export LD_LIBRARY_PATH=/usr/local/cuda-11.8/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
32-bit system:
export LD_LIBRARY_PATH=/usr/local/cuda-11.8/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
添加方式:sudo vim ~/.bashrc
打开文件 → i
进入插入状态 → 仿照上述语句输入 → Esc
退出插入状态 → :wq
保存并退出 → source ~/.bashrc
刷新
安装后执行 nvidia-smi
通常会有如下报错,重启即可。
NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running.
2.3 cuDNN
下载 → 解压 → 复制到 cuda 中 → 设置权限
tar -xvf cudnn-linux-$arch-8.x.x.x_cudaX.Y-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*
拷贝时
-P
选项表示保留源文件的原始属性,其中包括文件的符号链接属性(软链接)。通俗来说使用-P
时,会复制链接属性; 不使用-P
时会复制实际链接的文件。
chmod
更改文件权限,a
代表所有用户,+r
代表增加读取权限。
2.4 TensorRT
下载 → 解压 → 添加环境变量
tar -xzvf TensorRT-${version}.Linux.${arch}-gnu.${cuda}.tar.gz
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:<TensorRT-${version}/lib>
2.5 关于环境变量
在安装 CUDA、TensorRT 等都会涉及添加系统环境变量,例如:
export PATH=/usr/local/cuda-11.8/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda-11.8/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
这其中 PATH
代表可执行文件的搜索路径,经常用来验证安装、查看 CUDA 版本的指令 nvcc -V
,nvcc 就是在 bin 目录下的一个可执行文件。LD_LIBRARY_PATH
代表共享库的搜索路径,程序运行时需要加载的库文件会从该路径中寻找。
另外,不同的配置教程会看到一些不同的写法,例如:
export PATH=/usr/local/cuda-11.8/bin:$PATH
export PATH=$PATH:/usr/local/cuda-11.8/bin
export PATH=/usr/local/cuda-11.8/bin${PATH:+:${PATH}}
可以先通过 echo $PATH
查看,发现 PATH
的值就是多个路径,每个路径用冒号 :
隔开(开头和结尾没有冒号)。$PATH
就代表了 PATH
当前的值,所以第一句就是把 CUDA 的路径加到当前所有路径的最前面,而第二句是加到最后面,冒号用来做分隔符。系统在搜索可执行文件时会按照 PATH
变量路径的顺序从前往后搜索。
${PATH:+:${PATH}}
的语法为 ${VAR:+VALUE}
,代表变量 VAR
如果为空则返回空字符串,否则返回 VALUE
(此处为 :${PATH}
加了个冒号作分隔),这样的好处是当 PATH
为空时,结尾不会出现多余的冒号。
3. C++ 示例:sampleOnnxMNIST
进入 xxx/TensorRT-8.6.1.6/samples/sampleOnnxMNIST
,文件结构如下:
├── Makefile
├── README.md
└── sampleOnnxMNIST.cpp
由于提供的是 Makefile,直接在当前路径下 make
后会在 xxx/TensorRT-8.6.1.6/bin
目录下多出两个可执行文件和两个文件夹,文件结构如下。
├── chobj
│ └── sampleOnnxMNIST
│ ├── common
│ └── sampleOnnxMNIST
├── dchobj
│ └── sampleOnnxMNIST
│ ├── common
│ └── sampleOnnxMNIST
├── sample_onnx_mnist
├── sample_onnx_mnist_debug
└── trtexec
从文件命名可以看出生成了 Debug 和 Release 两个版本,文件夹内存储了编译过程中的中间文件。
cd TensorRT-8.6.1.6/bin
./sample_onnx_mnist
&&&& RUNNING TensorRT.sample_onnx_mnist [TensorRT v8601] # ./sample_onnx_mnist
[12/28/2023-11:47:01] [I] Building and running a GPU inference engine for Onnx MNIST
[12/28/2023-11:47:02] [I] [TRT] [MemUsageChange] Init CUDA: CPU +14, GPU +0, now: CPU 19, GPU 20276 (MiB)
[12/28/2023-11:47:20] [I] [TRT] [MemUsageChange] Init builder kernel library: CPU +1450, GPU +270, now: CPU 1545, GPU 20546 (MiB)
[12/28/2023-11:47:20] [I] [TRT] ----------------------------------------------------------------
[12/28/2023-11:47:20] [I] [TRT] Input filename: ../../../data/mnist/mnist.onnx
[12/28/2023-11:47:20] [I] [TRT] ONNX IR version: 0.0.3
[12/28/2023-11:47:20] [I] [TRT] Opset version: 8
[12/28/2023-11:47:20] [I] [TRT] Producer name: CNTK
[12/28/2023-11:47:20] [I] [TRT] Producer version: 2.5.1
[12/28/2023-11:47:20] [I] [TRT] Domain: ai.cntk
[12/28/2023-11:47:20] [I] [TRT] Model version: 1
[12/28/2023-11:47:20] [I] [TRT] Doc string:
[12/28/2023-11:47:20] [I] [TRT] ----------------------------------------------------------------
[12/28/2023-11:47:20] [W] [TRT] onnx2trt_utils.cpp:374: Your ONNX model has been generated with INT64 weights, while TensorRT does not natively support INT64. Attempting to cast down to INT32.
[12/28/2023-11:47:20] [I] [TRT] Graph optimization time: 0.0045733 seconds.
[12/28/2023-11:47:20] [I] [TRT] Local timing cache in use. Profiling results in this builder pass will not be stored.
[12/28/2023-11:47:42] [I] [TRT] Detected 1 inputs and 1 output network tensors.
[12/28/2023-11:47:42] [I] [TRT] Total Host Persistent Memory: 22448
[12/28/2023-11:47:42] [I] [TRT] Total Device Persistent Memory: 0
[12/28/2023-11:47:42] [I] [TRT] Total Scratch Memory: 0
[12/28/2023-11:47:42] [I] [TRT] [MemUsageStats] Peak memory usage of TRT CPU/GPU memory allocators: CPU 0 MiB, GPU 4 MiB
[12/28/2023-11:47:42] [I] [TRT] [BlockAssignment] Started assigning block shifts. This will take 6 steps to complete.
[12/28/2023-11:47:42] [I] [TRT] [BlockAssignment] Algorithm ShiftNTopDown took 0.034813ms to assign 3 blocks to 6 nodes requiring 32256 bytes.
[12/28/2023-11:47:42] [I] [TRT] Total Activation Memory: 31744
[12/28/2023-11:47:42] [I] [TRT] [MemUsageChange] TensorRT-managed allocation in building engine: CPU +0, GPU +4, now: CPU 0, GPU 4 (MiB)
[12/28/2023-11:47:42] [I] [TRT] Loaded engine size: 1 MiB
[12/28/2023-11:47:42] [I] [TRT] [MemUsageChange] TensorRT-managed allocation in engine deserialization: CPU +0, GPU +0, now: CPU 0, GPU 0 (MiB)
[12/28/2023-11:47:43] [I] [TRT] [MemUsageChange] TensorRT-managed allocation in IExecutionContext creation: CPU +0, GPU +0, now: CPU 0, GPU 0 (MiB)
[12/28/2023-11:47:43] [I] Input:
[12/28/2023-11:47:43] [I] @@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@%.:@@@@@@@@@@@@
@@@@@@@@@@@@@: *@@@@@@@@@@@@
@@@@@@@@@@@@* =@@@@@@@@@@@@@
@@@@@@@@@@@% :@@@@@@@@@@@@@@
@@@@@@@@@@@- *@@@@@@@@@@@@@@
@@@@@@@@@@# .@@@@@@@@@@@@@@@
@@@@@@@@@@: #@@@@@@@@@@@@@@@
@@@@@@@@@+ -@@@@@@@@@@@@@@@@
@@@@@@@@@: %@@@@@@@@@@@@@@@@
@@@@@@@@+ +@@@@@@@@@@@@@@@@@
@@@@@@@@:.%@@@@@@@@@@@@@@@@@
@@@@@@@% -@@@@@@@@@@@@@@@@@@
@@@@@@@% -@@@@@@#..:@@@@@@@@
@@@@@@@% +@@@@@- :@@@@@@@
@@@@@@@% =@@@@%.#@@- +@@@@@@
@@@@@@@@..%@@@*+@@@@ :@@@@@@
@@@@@@@@= -%@@@@@@@@ :@@@@@@
@@@@@@@@@- .*@@@@@@+ +@@@@@@
@@@@@@@@@@+ .:-+-: .@@@@@@@
@@@@@@@@@@@@+: :*@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@
[12/28/2023-11:47:43] [I] Output:
[12/28/2023-11:47:43] [I] Prob 0 0.0000 Class 0:
[12/28/2023-11:47:43] [I] Prob 1 0.0000 Class 1:
[12/28/2023-11:47:43] [I] Prob 2 0.0000 Class 2:
[12/28/2023-11:47:43] [I] Prob 3 0.0000 Class 3:
[12/28/2023-11:47:43] [I] Prob 4 0.0000 Class 4:
[12/28/2023-11:47:43] [I] Prob 5 0.0000 Class 5:
[12/28/2023-11:47:43] [I] Prob 6 1.0000 Class 6: **********
[12/28/2023-11:47:43] [I] Prob 7 0.0000 Class 7:
[12/28/2023-11:47:43] [I] Prob 8 0.0000 Class 8:
[12/28/2023-11:47:43] [I] Prob 9 0.0000 Class 9:
[12/28/2023-11:47:43] [I]
&&&& PASSED TensorRT.sample_onnx_mnist [TensorRT v8601] # ./sample_onnx_mnist
4. Python 示例:network_api_pytorch_mnist
4.1 Python 环境
conda create -n trt python=3.8
conda activate trt
查看示例提供的 requirements.txt
,里面默认是 CPU 版 Pytorch。手动安装 GPU 版 Pytorch 和其他库,print(torch.cuda.is_available())
验证。
Pytorch 安装:https://pytorch.org/get-started/previous-versions/
Torch-TensorRT:https://pytorch.org/TensorRT/
如果要使用 PyTorch 框架内的 TensorRT 接口推理模型,需要安装 pip install torch-tensorrt
。当前版本(2024.01) torch-tensorrt 1.4.0
需要 2.0.1<=torch<2.1
,因此先安装 2.0.1 版本的 PyTorch。
conda install pytorch==2.0.1 torchvision==0.15.2 torchaudio==2.0.2 pytorch-cuda=11.8 -c pytorch -c nvidia
pip install cuda-python
按官方文档安装 TensorRT
(1)Python TensorRT wheel file(选择对应 Python 版本)
cd TensorRT-8.6.1.6/python/
python3 -m pip install tensorrt-8.6.1-cp38-none-linux_x86_64.whl
(可选)TensorRT lean and dispatch runtime wheel files(未安装)
python3 -m pip install tensorrt_lean-8.6.1-cp38-none-linux_x86_64.whl
python3 -m pip install tensorrt_dispatch-8.6.1-cp38-none-linux_x86_64.whl
-m
用于确保使用与当前 Python 解释器版本匹配的 pip 模块,可以省略
(2)Python UFF wheel file(仅当 TensorRT 与 UFF 格式的 TensorFlow 一起使用时安装)
cd TensorRT-8.6.1.6/uff
python3 -m pip install uff-0.6.9-py2.py3-none-any.whl
验证安装:which convert-to-uff
(3)Python graphsurgeon wheel file
cd TensorRT-8.6.1.6/graphsurgeon
python3 -m pip install graphsurgeon-0.4.6-py2.py3-none-any.whl
(4)Python onnx-graphsurgeon wheel file
cd TensorRT-8.6.1.6/onnx_graphsurgeon
python3 -m pip install onnx_graphsurgeon-0.3.12-py2.py3-none-any.whl
4.2 运行示例
python3 sample.py
Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz to /tmp/mnist/data/MNIST/raw/train-images-idx3-ubyte.gz
100.0%
Extracting /tmp/mnist/data/MNIST/raw/train-images-idx3-ubyte.gz to /tmp/mnist/data/MNIST/raw
Downloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz to /tmp/mnist/data/MNIST/raw/train-labels-idx1-ubyte.gz
100.0%
Extracting /tmp/mnist/data/MNIST/raw/train-labels-idx1-ubyte.gz to /tmp/mnist/data/MNIST/raw
Downloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz to /tmp/mnist/data/MNIST/raw/t10k-images-idx3-ubyte.gz
100.0%
Extracting /tmp/mnist/data/MNIST/raw/t10k-images-idx3-ubyte.gz to /tmp/mnist/data/MNIST/raw
Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz to /tmp/mnist/data/MNIST/raw/t10k-labels-idx1-ubyte.gz
100.0%
Extracting /tmp/mnist/data/MNIST/raw/t10k-labels-idx1-ubyte.gz to /tmp/mnist/data/MNIST/raw
Train Epoch: 1 [0/60000 (0%)] Loss: 2.285434
Train Epoch: 1 [6400/60000 (11%)] Loss: 0.432527
Train Epoch: 1 [12800/60000 (21%)] Loss: 0.334675
Train Epoch: 1 [19200/60000 (32%)] Loss: 0.336500
Train Epoch: 1 [25600/60000 (43%)] Loss: 0.083923
Train Epoch: 1 [32000/60000 (53%)] Loss: 0.189684
Train Epoch: 1 [38400/60000 (64%)] Loss: 0.195426
Train Epoch: 1 [44800/60000 (75%)] Loss: 0.076821
Train Epoch: 1 [51200/60000 (85%)] Loss: 0.141365
Train Epoch: 1 [57600/60000 (96%)] Loss: 0.098627
Test set: Average loss: 0.0889, Accuracy: 9717/10000 (97%)
Train Epoch: 2 [0/60000 (0%)] Loss: 0.064764
Train Epoch: 2 [6400/60000 (11%)] Loss: 0.018003
Train Epoch: 2 [12800/60000 (21%)] Loss: 0.051768
Train Epoch: 2 [19200/60000 (32%)] Loss: 0.060859
Train Epoch: 2 [25600/60000 (43%)] Loss: 0.103904
Train Epoch: 2 [32000/60000 (53%)] Loss: 0.133826
Train Epoch: 2 [38400/60000 (64%)] Loss: 0.055738
Train Epoch: 2 [44800/60000 (75%)] Loss: 0.030482
Train Epoch: 2 [51200/60000 (85%)] Loss: 0.037646
Train Epoch: 2 [57600/60000 (96%)] Loss: 0.115068
Test set: Average loss: 0.0557, Accuracy: 9839/10000 (98%)
sample.py:112: DeprecationWarning: Use set_memory_pool_limit instead.
config.max_workspace_size = common.GiB(1)
sample.py:75: DeprecationWarning: Use add_convolution_nd instead.
conv1 = network.add_convolution(
sample.py:78: DeprecationWarning: Use stride_nd instead.
conv1.stride = (1, 1)
sample.py:80: DeprecationWarning: Use add_pooling_nd instead.
pool1 = network.add_pooling(input=conv1.get_output(0), type=trt.PoolingType.MAX, window_size=(2, 2))
sample.py:81: DeprecationWarning: Use stride_nd instead.
pool1.stride = (2, 2)
sample.py:85: DeprecationWarning: Use add_convolution_nd instead.
conv2 = network.add_convolution(pool1.get_output(0), 50, (5, 5), conv2_w, conv2_b)
sample.py:86: DeprecationWarning: Use stride_nd instead.
conv2.stride = (1, 1)
sample.py:88: DeprecationWarning: Use add_pooling_nd instead.
pool2 = network.add_pooling(conv2.get_output(0), trt.PoolingType.MAX, (2, 2))
sample.py:89: DeprecationWarning: Use stride_nd instead.
pool2.stride = (2, 2)
Test Case: 6
Prediction: 6