这俩天摸鱼玩耍有些多 (比平时多),电脑 (另一台有双系统的) 忘了带着了…
我的环境和代码都在那台机子上呢… 彳亍口巴,windows 上新配置一个TensorRT环境
咱就根据官方指南 TensorRT 8.4.1 来搞:
https://docs.nvidia.com/deeplearning/tensorrt/install-guide/index.html
有一句:
Starting in TensorRT version 8.4.1, Python support for Windows included in the zip package is ready for production use.
从Trt 8.4.1 版本开始,Windows 的 Python 支持已经可以在 zip 包搞定了
1. Pycuda 安装
先从简单的来吧,直接 pip 安装,在你的那个环境
pip install pycuda
直接这样安装可能会有对应的问题:
ERROR: Could not build wheels for pycuda, which is required to install pyproject.toml-based projects
官方安装指南的意思是,你可以编译安装hhhhh
也可以从这个经典的网站下载:
https://www.lfd.uci.edu/~gohlke/pythonlibs/#pycuda
我的 Python版本是3.8,CUDA版本是 11.6,选择这个安装
下载完毕后:
pip install "pycuda-2022.1+cuda116-cp38-cp38-win_amd64.whl"
安装完毕,建议按照这篇博客的内容测试一下
pycuda 安装完毕,验证步骤
看看有没有成功,(主要是cl.exe
是否存在以及是否在环境变量中的问题)
如果找不到cl.exe
可以参考这里:
找不到 cl.exe 解决办法
2. CUDA支持
当前 TRT8.4.1
工具包需要 CUDA 依赖,当前 TRT 可以与 以上版本的 CUDA 兼容,如果你的CUDA版本旧了,那就重新安装一下CUDA
Choose where you want to install TensorRT. The zip file will install everything into a subdirectory called TensorRT-8.x.x.x. This new subdirectory will be referred to as <installpath> in the steps below.
选择一个你要安装 TensorRT 的位置, 解压zip包即可,zip包解压后会产生一个子路径
TensorRT-8.x.x.x
.
我的文件名字是 TensorRT-8.4.1.5.Windows10.x86_64.cuda-11.6.cudnn8.4.zip
(这个等下说在哪里下载)
8.4.1.5 是 TensorRT 版本,CUDA版本是11.6,cudnn版本是8.4
诸位可以通过这个脚本来看自己的环境,唯一的第三方依赖是 paddle,需要安装一下GPU的版本
Python 读取主机信息:https://blog.csdn.net/HaoZiHuang/article/details/125565362
这是我最终的执行结果,可以看到 cudnn 版本是8.3,比刚才提到的 TensorRT 需要cudnn8.4 稍微低了一些,但愿可以向下兼容,不行的话,重装一下 cudnn8.4 即可. 实际证明 cudnn8.3 也是可以的,但是在使用过程中,可能会有这个warning:
3. 下载解压zip包
从官网下载 windows 的预编译 trt 包
https://developer.nvidia.com/nvidia-tensorrt-download
注意看你的CUDA版本哈,还有上边是linux的,下边是windows的
下载下来的名字是: TensorRT-8.4.1.5.Windows10.x86_64.cuda-11.6.cudnn8.4.zip
,解压即可
这是trt那个zip解压后的样子:
我就安装在C盘了,因为我只有一个盘
这里有值得说叨的东西
- 一是这个bin目录下有个
trtexec.exe
工具,这个好用的一批,可以用来onnx模型转化为 trt 模型,而且可以用来测试 trt 模型性能之类的. - 二是这个python目录,打开看看
一些可以直接安装的whl文件,直接pip安装就好,注意要根据自己的Python版本做选择
# 我是Python3.8,看那个 cp
pip install tensorrt-8.4.1.5-cp38-none-win_amd64.whl
4. 添加环境变量
接下来最重要的一步,就是将TensorRT的library文件(库文件)添加到环境变量中,官方的安装指导文件给出了两种方法:
- 要么直接将
<TensorRT installpath>/lib
添加到环境变量PATH
中 (诶,windows没有LD_LIBRARY_PATH
这个环境变量吗) - 要么将
<TensorRT installpath>/lib
下的DLL文件,复制到CUDA安装目录,例如这个路径C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\vX.Y\bin
,vX.Y
是CUDA版本,当然了,这个CUDA安装路径,已经在环境变量PATH
中了 (你要是连CUDA也没安装,先去安装CUDA吧),可以参考这篇:
https://blog.csdn.net/HaoZiHuang/article/details/107868005
在此处,我选择第一种方法,第二种方法不方便维护,随便啦,都可:
当然,推荐把 <TensorRT installpath>/bin
也添加到环境变量Path
中,然后就在命令行直接使用 trtexec
工具了
cmd执行一下,显示这个就OK
5. 验证TRT环境
从这个链接撸了一段代码,并做了一部分改动:
https://stackoverflow.com/questions/59280745/inference-with-tensorrt-engine-file-on-python
import tensorrt as trt
import numpy as np
import os
import pycuda.driver as cuda
import pycuda.autoinit
import cv2
import matplotlib.pyplot as plt
class HostDeviceMem(object):
def __init__(self, host_mem, device_mem):
self.host = host_mem
self.device = device_mem
def __str__(self):
return "Host:\n" + str(self.host) + "\nDevice:\n" + str(self.device)
def __repr__(self):
return self.__str__()
class TrtModel:
def __init__(self,engine_path, max_batch_size=1, dtype=np.float32):
self.engine_path = engine_path
self.dtype = dtype
self.logger = trt.Logger(trt.Logger.WARNING)
self.runtime = trt.Runtime(self.logger)
self.engine = self.load_engine(self.runtime, self.engine_path)
self.max_batch_size = max_batch_size
self.inputs, self.outputs, self.bindings, self.stream = self.allocate_buffers()
self.context = self.engine.create_execution_context()
@staticmethod
def load_engine(trt_runtime, engine_path):
trt.init_libnvinfer_plugins(None, "")
with open(engine_path, 'rb') as f:
engine_data = f.read()
engine = trt_runtime.deserialize_cuda_engine(engine_data)
return engine
def allocate_buffers(self):
inputs = []
outputs = []
bindings = []
stream = cuda.Stream()
for binding in self.engine:
size = trt.volume(self.engine.get_binding_shape(binding)) * self.max_batch_size
host_mem = cuda.pagelocked_empty(size, self.dtype)
device_mem = cuda.mem_alloc(host_mem.nbytes)
bindings.append(int(device_mem))
if self.engine.binding_is_input(binding):
inputs.append(HostDeviceMem(host_mem, device_mem))
else:
outputs.append(HostDeviceMem(host_mem, device_mem))
return inputs, outputs, bindings, stream
def __call__(self,x:np.ndarray,batch_size=2):
x = x.astype(self.dtype)
np.copyto(self.inputs[0].host,x.ravel())
for inp in self.inputs:
cuda.memcpy_htod_async(inp.device, inp.host, self.stream)
self.context.execute_async(batch_size=batch_size, bindings=self.bindings, stream_handle=self.stream.handle)
for out in self.outputs:
cuda.memcpy_dtoh_async(out.host, out.device, self.stream)
self.stream.synchronize()
return [out.host.reshape(batch_size,-1) for out in self.outputs]
if __name__ == "__main__":
batch_size = 1
trt_engine_path = os.path.join("out.engine") # 这里是 Trt 模型的位置
model = TrtModel(trt_engine_path)
shape = model.engine.get_binding_shape(0)
img_path = "dasima.jpeg" # <--------------- 这里传入照片
# 以下是图片预处理
data = cv2.imread(img_path)
ori_shape = data.shape[:-1]
data = cv2.resize(data, (224, 224)) / 255 # 224 可能也需要改,我模型的输入是224
data = data.transpose(2, 0, 1)
data = data[None]
# 前向传播
result = model(data, batch_size)[0]
# 进行后处理,因为其返回是一个一维的张量
result = result.reshape(2, 224, 224).argmax(axis=0).astype(np.uint8)
result = cv2.resize(result, ori_shape[::-1], cv2.INTER_LINEAR)
plt.imshow(result)
plt.show()
OKOK了,感谢金轮老铁的照片,代码只需要改一下,照片路径,trt/engine 模型的路径,已经图片resize的大小
最后补充一下 trt文件和engine文件的区别:
二者除了后缀名不同,其他都一样
参考自:
https://forums.developer.nvidia.com/t/whats-the-difference-between-engine-file-and-trt-file/109766