TensorRT综述

简介: TensorRT综述

TensorRT综述


概述


TensorRT是NVIDIA提供的用于深度学习推理的高性能推理引擎,它可以优化深度学习模型的推理速度和性能,以满足实时应用的需求。


TensorRT采用了多种优化技术,包括网络剪枝、量化、层融合等,可以自动优化网络结构以减少运行时间和内存占用。与常规的深度学习框架相比,TensorRT可以将模型的推理速度提高数倍,同时减少了计算和内存的开销。


TensorRT支持多种类型的神经网络,包括卷积神经网络、循环神经网络、生成对抗网络等,可以在多种平台上运行,包括GPU、CPU、嵌入式设备等。同时,TensorRT还提供了C++和Python API,可以方便地集成到现有的深度学习框架和应用程序中。


总之,TensorRT是一款优秀的深度学习推理引擎,可以大大提高深度学习模型的推理速度和性能,适用于许多实时应用场景。


环境搭建(基于docker环境)


Docker环境有以下几个优势:


1.跨平台:Docker容器可以在不同的操作系统上运行,包括Linux、Windows、Mac等,这使得应用程序可以更加容易地在不同的环境中部署和运行。


2.隔离性:Docker容器提供了一种隔离应用程序的方式,使得应用程序不会互相干扰,同时可以避免不同应用程序之间的依赖冲突。这样可以让应用程序更加稳定、可靠,也更容易管理。


3.可移植性:Docker容器是一种轻量级的虚拟化技术,可以将应用程序和其依赖项打包到一个镜像中,并在不同的环境中运行,这使得应用程序可以更加方便地进行部署、迁移和扩展。


4.快速部署:使用Docker容器可以极大地简化应用程序的部署过程,只需要将容器部署到目标环境中即可,无需安装依赖项、配置环境等繁琐的过程。


5.可伸缩性:Docker容器可以在多个主机上运行,并可以通过Docker Swarm等容器编排工具进行管理,从而实现应用程序的快速扩展和伸缩。


总之,Docker环境可以让应用程序更加轻量、可移植、可靠,同时也更容易部署和管理。这使得Docker成为了现代应用程序开发和部署的重要工具之一。


  • 进入NVIDIA官网
https://catalog.ngc.nvidia.com/orgs/nvidia/containers/tensorrt/tags
  • 选择需要的tensorrt版本
  • 13.png
  • 下载TensorRT docker镜像
docker pull nvcr.io/nvidia/tensorrt:21.07-py3
  • 启动容器,并进入镜像
docker run --gpus all -it --rm -v /work/jxp/project/:/models nvcr.io/nvidia/tensorrt:21.07-py3
  • 安装opencv
pip install opencv-python-headless -i https://pypi.doubanio.com/simple

注意:如果安装opencv-python会报错ImportError: libGL.so.1: cannot open shared object file: No such file or directory


ONNX转TensorRT


  • 全精度转换(FP32)
trtexec --onnx=efficientnet.onnx --explicitBatch --minShapes=input:1x3x224x224 --optShapes=input:16x3x224x224 --maxShapes=input:32x3x224x224 --saveEngine=efficientnet.plan --verbose
  • 半精度转换(FP16)
 trtexec --onnx=efficientnet.onnx --explicitBatch --minShapes=input:1x3x224x224 --optShapes=input:16x3x224x224 --maxShapes=input:32x3x224x224 --saveEngine=efficientnet.plan  --fp16 --verbose

TensorRT 推理


TensorRT推理的流程一般包括以下几个步骤:


1.定义模型:首先需要定义深度学习模型,可以使用常见的深度学习框架(如TensorFlow、PyTorch等)或者使用C++或Python API直接定义模型。


2.优化模型:使用TensorRT进行模型优化,包括层融合、剪枝、量化、深度缩减等优化技术,以达到加速和减小模型大小的目的。


3.创建执行引擎:将优化后的模型转化为TensorRT执行引擎,以供后续推理使用。执行引擎包括计算图、内存分配、网络优化等信息,可以根据需要序列化到文件中。


4.加载数据:将输入数据加载到内存中,包括图像、音频、文本等数据。


5.前处理:对输入数据进行前处理,包括归一化、裁剪、缩放、格式转换等操作,以满足模型输入的要求。


6.推理计算:将前处理后的数据输入到TensorRT执行引擎中进行推理计算,得到输出结果。


7.后处理:对输出结果进行后处理,包括格式转换、解码、可视化等操作,以满足应用程序的需求。


8.输出结果:将后处理后的输出结果输出到文件、数据库、网络等存储介质中,以供后续应用程序使用。


总之,TensorRT推理的流程包括了模型定义、模型优化、执行引擎创建、数据加载、前处理、推理计算、后处理、输出结果等多个步骤,需要综合考虑各个步骤的性能、准确性、可靠性等因素,以满足应用程序的需求。


加载EfficientNet TensorRT模型

#---------------------------------------------------------------
#   加载EfficientNet TensorRT模型
#---------------------------------------------------------------
engine_file_path = "/path/to/efficientnet.engine"
with open(engine_file_path, "rb") as f, trt.Runtime(trt.Logger()) as runtime:
    engine = runtime.deserialize_cuda_engine(f.read())
    context = engine.create_execution_context()

分配GPU、将输入数据复制到GPU内存中、将输出数据从GPU内存复制到主机内存中

    #---------------------------------------------------------------
    #   分配GPU、将输入数据复制到GPU内存中、将输出数据从GPU内存复制到主机内存中
    #---------------------------------------------------------------
    def allocate_buffers(self, engine, max_batch_size=32):
        inputs = []
        outputs = []
        bindings = []
        stream = cuda.Stream()
        for binding in engine:
            dims = engine.get_binding_shape(binding)
            # print(dims)
            if dims[0] == -1:
                assert(max_batch_size is not None)
                dims[0] = max_batch_size  # 动态batch_size适应
            size = trt.volume(dims) * engine.max_batch_size
            dtype = trt.nptype(engine.get_binding_dtype(binding))
            host_mem = cuda.pagelocked_empty(size, dtype)  # 开辟出一片显存
            device_mem = cuda.mem_alloc(host_mem.nbytes)
            bindings.append(int(device_mem))
            if 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 img_pre_process(self, img):
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        img = cv2.resize(img, (self.input_size[1], self.input_size[0]), interpolation=cv2.INTER_LINEAR)
        try:
            cv2.imwrite("test.jpg", img)
            img = img.astype(np.float32)
            img /= 255.0
            img_mean = (0.485,0.456,0.406)
            img_std = (0.229,0.224,0.225)
            img = img - img_mean
            img = (img/img_std)
        except Exception as e:
            print("img_pre_process===wrong!!!",e)
        return img
    def pre_process(self, img_list):
        self.batch_size = len(img_list)
        batch_img = []
        self.batch_data = []
        self.context.set_binding_shape(0, (self.batch_size, 3, self.input_size[0], self.input_size[1]))
        self.inputs, self.outputs, self.bindings, self.stream = self.allocate_buffers(
            self.engine, max_batch_size=self.batch_size)  # 构建输入,输出,流指针
        imgs_result = self.thread_pool.map(self.img_pre_process, img_list)
        imgs_list_res = list(zip(imgs_result))
        for r in imgs_list_res:
            batch_img.append(r[0])
        self.batch_data = np.stack(batch_img, axis=0)
        return self.batch_data

推理

    #---------------------------------------------------------------
    #   推理
    #---------------------------------------------------------------
    def do_inference_v2(self, context, bindings, inputs, outputs, stream):
        [cuda.memcpy_htod_async(inp.device, inp.host, stream) for inp in inputs]
        context.execute_async_v2(bindings=bindings, stream_handle=stream.handle)
        [cuda.memcpy_dtoh_async(out.host, out.device, stream) for out in outputs]
        stream.synchronize()
        return [out.host for out in outputs]
    def model_predict(self):
        np.copyto(self.inputs[0].host, self.batch_data.ravel())
        result = self.do_inference_v2(self.context, self.bindings, self.inputs, self.outputs, self.stream)[0]
        return result

后处理

#---------------------------------------------------------------
#   推理
#---------------------------------------------------------------
def post_process(self,result):
    result = result.reshape(-1,4)
    for r in result:
        index = np.argmax(r, axis=0)
        print("=======index===========",index)

完整代码:

import os
import time
import glob
import cv2
import numpy as np
import pycuda.autoinit
import pycuda.driver as cuda
import tensorrt as trt
import concurrent.futures
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(object):
    def __init__(self, engine_path, input_size):
        try:
            self.engine_path = engine_path
            TRT_LOGGER = trt.Logger(trt.Logger.WARNING)
            self.runtime = trt.Runtime(TRT_LOGGER)
            self.engine = self.load_engine(self.runtime, self.engine_path)
            self.context = self.engine.create_execution_context()
            self.thread_pool = concurrent.futures.ThreadPoolExecutor()
            self.input_size = input_size
        except Exception as e:
            print("TrtModel******init*********wrong")
    # 加载EfficientNet TensorRT模型
    def load_engine(self, trt_runtime, engine_path):
        try:
            with open(engine_path, "rb") as f:
                engine_data = f.read()
            engine = trt_runtime.deserialize_cuda_engine(engine_data)
        except Exception as e:
            print("load_engine filled")
        return engine
    # 分配GPU内存、将输入数据复制到GPU内存中、将输出数据从GPU内存复制到主机内存中
    def allocate_buffers(self, engine, max_batch_size=32):
        inputs = []
        outputs = []
        bindings = []
        stream = cuda.Stream()
        for binding in engine:
            dims = engine.get_binding_shape(binding)
            if dims[0] == -1:
                assert(max_batch_size is not None)
                dims[0] = max_batch_size  # 动态batch_size适应
            size = trt.volume(dims) * engine.max_batch_size
            dtype = trt.nptype(engine.get_binding_dtype(binding))
            host_mem = cuda.pagelocked_empty(size, dtype)  # 开辟出一片显存
            device_mem = cuda.mem_alloc(host_mem.nbytes)
            bindings.append(int(device_mem))
            if 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 img_pre_process(self, img):
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        img = cv2.resize(img, (self.input_size[1], self.input_size[0]), interpolation=cv2.INTER_LINEAR)
        try:
            cv2.imwrite("test.jpg", img)
            img = img.astype(np.float32)
            img /= 255.0
            img_mean = (0.485,0.456,0.406)
            img_std = (0.229,0.224,0.225)
            img = img - img_mean
            img = (img/img_std)
        except Exception as e:
            print("img_pre_process===wrong!!!",e)
        return img
    def pre_process(self, img_list):
        self.batch_size = len(img_list)
        batch_img = []
        self.batch_data = []
        self.context.set_binding_shape(0, (self.batch_size, 3, self.input_size[0], self.input_size[1]))
        self.inputs, self.outputs, self.bindings, self.stream = self.allocate_buffers(
            self.engine, max_batch_size=self.batch_size)  # 构建输入,输出,流指针
        imgs_result = self.thread_pool.map(self.img_pre_process, img_list)
        imgs_list_res = list(zip(imgs_result))
        for r in imgs_list_res:
            batch_img.append(r[0])
        self.batch_data = np.stack(batch_img, axis=0)
        return self.batch_data
    #---------------------------------------------------------------
    #   推理
    #---------------------------------------------------------------
    def do_inference_v2(self, context, bindings, inputs, outputs, stream):
        [cuda.memcpy_htod_async(inp.device, inp.host, stream) for inp in inputs]
        context.execute_async_v2(bindings=bindings, stream_handle=stream.handle)
        [cuda.memcpy_dtoh_async(out.host, out.device, stream) for out in outputs]
        stream.synchronize()
        return [out.host for out in outputs]
    def model_predict(self):
        np.copyto(self.inputs[0].host, self.batch_data.ravel())
        result = self.do_inference_v2(self.context, self.bindings, self.inputs, self.outputs, self.stream)[0]
        return result
    #---------------------------------------------------------------
    #   后处理
    #---------------------------------------------------------------
    def post_process(self,result):
        result = result.reshape(-1,4)
        for r in result:
            index = np.argmax(r, axis=0)
            print("=======index===========",index)
if __name__ == "__main__":
    img_path = 'data/'
    engine_path = 'model.plan'
    img_list = []
    for img in os.listdir(img_path):
        img_p = os.path.join(img_path,img)
        img_ = cv2.imread(img_p)
        img_list.append(img_)
    input_size = [224,224]
    trt_model = TrtModel(engine_path, input_size)
    trt_model.pre_process(img_list)
    result = trt_model.model_predict()
    trt_model.post_process(result)
相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
目录
相关文章
|
8月前
|
机器学习/深度学习 PyTorch API
PyTorch 深度学习实用指南:6~8
PyTorch 深度学习实用指南:6~8
137 0
|
8月前
|
机器学习/深度学习 PyTorch 算法框架/工具
PyTorch 深度学习实用指南:1~5
PyTorch 深度学习实用指南:1~5
207 0
|
2月前
|
机器学习/深度学习 人工智能 TensorFlow
基于TensorFlow的深度学习模型训练与优化实战
基于TensorFlow的深度学习模型训练与优化实战
103 0
|
7月前
|
机器学习/深度学习 人工智能 PyTorch
PyTorch快速入门与深度学习模型训练
这篇文章是PyTorch的入门指南,介绍了PyTorch作为深度学习框架的基本概念和使用方法。内容包括PyTorch的背景、基础操作如张量创建、运算、自动微分,以及如何构建和训练简单的全连接神经网络模型进行MNIST手写数字识别。通过这篇文章,读者可以快速了解如何在PyTorch中搭建和训练深度学习模型。
367 4
|
8月前
|
机器学习/深度学习 PyTorch API
pytorch与深度学习
【5月更文挑战第3天】PyTorch,Facebook开源的深度学习框架,以其动态计算图和灵活API深受青睐。本文深入浅出地介绍PyTorch基础,包括动态计算图、张量和自动微分,通过代码示例演示简单线性回归和卷积神经网络的实现。此外,探讨了模型架构、自定义层、数据加载及预处理等进阶概念,并分享了实战技巧、问题解决方案和学习资源,助力读者快速掌握PyTorch。
78 5
|
7月前
|
机器学习/深度学习 自然语言处理 PyTorch
PyTorch与深度学习
PyTorch与深度学习
28 0
|
8月前
|
机器学习/深度学习 自然语言处理 算法
【深度学习】与【PyTorch实战】
【深度学习】与【PyTorch实战】
|
8月前
|
机器学习/深度学习 PyTorch TensorFlow
TensorFlow vs PyTorch:深度学习框架的比较研究
TensorFlow vs PyTorch:深度学习框架的比较研究
92 1
|
8月前
|
机器学习/深度学习 PyTorch TensorFlow
深度学习模型加速:Pytorch模型转TensorRT模型
深度学习模型加速:Pytorch模型转TensorRT模型
315 0
|
机器学习/深度学习 人工智能 PyTorch
PyTorch深度学习实战 | 深度学习框架(PyTorch)
PyTorch是当前主流深度学习框架之一,其设计追求最少的封装、最直观的设计,其简洁优美的特性使得PyTorch代码更易理解,对新手非常友好。 本文主要介绍深度学习框架中PyTorch部分。
421 0
PyTorch深度学习实战 | 深度学习框架(PyTorch)