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)
相关实践学习
在云上部署ChatGLM2-6B大模型(GPU版)
ChatGLM2-6B是由智谱AI及清华KEG实验室于2023年6月发布的中英双语对话开源大模型。通过本实验,可以学习如何配置AIGC开发环境,如何部署ChatGLM2-6B大模型。
目录
相关文章
|
传感器 数据采集 算法
【软件设计师备考 专题 】系统可靠性分析评价
【软件设计师备考 专题 】系统可靠性分析评价
673 0
|
机器学习/深度学习 存储 并行计算
一篇就够:高性能推理引擎理论与实践 (TensorRT)
本文分享了关于 NVIDIA 推出的高性能的深度学习推理引擎 TensorRT 的背后理论知识和实践操作指南。
14825 9
一篇就够:高性能推理引擎理论与实践 (TensorRT)
Yum工具详解(二)-----Yum配置阿里源
Yum工具详解(二)-----Yum配置阿里源
5335 1
|
8月前
|
机器学习/深度学习 自然语言处理 数据可视化
基于图神经网络的自然语言处理:融合LangGraph与大型概念模型的情感分析实践
本文探讨了在企业数字化转型中,大型概念模型(LCMs)与图神经网络结合处理非结构化文本数据的技术方案。LCMs突破传统词汇级处理局限,以概念级语义理解为核心,增强情感分析、实体识别和主题建模能力。通过构建基于LangGraph的混合符号-语义处理管道,整合符号方法的结构化优势与语义方法的理解深度,实现精准的文本分析。具体应用中,该架构通过预处理、图构建、嵌入生成及GNN推理等模块,完成客户反馈的情感分类与主题聚类。最终,LangGraph工作流编排确保各模块高效协作,为企业提供可解释性强、业务价值高的分析结果。此技术融合为挖掘非结构化数据价值、支持数据驱动决策提供了创新路径。
497 6
基于图神经网络的自然语言处理:融合LangGraph与大型概念模型的情感分析实践
|
7月前
|
数据采集 自然语言处理 调度
优化通义大模型推理性能:企业级场景下的延迟与成本削减策略
本文基于金融、电商、医疗等领域的实战经验,深入探讨通义千问等大模型的推理优化技术栈。从计算图优化、批处理策略、量化压缩到系统架构四个维度展开,结合Python代码示例与压力测试数据,提供企业级解决方案。针对延迟敏感、高吞吐及成本敏感场景,分析性能瓶颈并提出算子融合、动态批处理、混合精度量化等方法,同时设计分布式推理架构与冷启动优化策略。通过案例展示,如电商大促场景优化,实现峰值QPS提升6.5倍、P99延迟降低53%、月度成本下降62%。文章还提供优化实施路线图,助力企业分阶段落地技术方案。
832 5
|
11月前
|
机器学习/深度学习 自然语言处理 算法
《深度解析:全连接层—卷积神经网络中的关键纽带》
全连接层在卷积神经网络(CNN)中起着桥梁作用,将卷积层和池化层提取的局部特征整合为全局特征,实现分类或回归任务。每个神经元与前一层所有神经元相连,通过权重和偏置进行特征转换,并引入激活函数以增强非线性建模能力。尽管参数量大易导致过拟合,但可通过正则化、Dropout和批标准化等技术有效应对,从而提升模型性能。
1010 8
|
前端开发 JavaScript 搜索推荐
构建简易天气预报应用
【8月更文挑战第31天】在这篇文章中,我们将一起踏上制作一个简易天气预报应用的旅程。不同于常规的技术文章摘要,这里我们直接潜入主题的核心——如何从零开始,利用HTML、CSS和JavaScript构建一个功能完备的天气预报工具。我们会探索API的使用,理解异步编程概念,并实现一个响应式设计的用户界面。准备好迎接代码和创意的结合,让我们动手实践,共同打造属于你的天气小助手!
|
11月前
|
存储 缓存 算法
JDK11升级后竟让内存利用率飙升到90%以上?
JDK11升级后竟让内存利用率飙升到90%以上?
|
搜索推荐 API 索引
Django中使用Elasticsearch进行搜索
Django中使用Elasticsearch进行搜索
505 0
|
传感器 Linux API
远程处理器消息框架(RPMSG) 【ChatGPT】
远程处理器消息框架(RPMSG) 【ChatGPT】