相关文章推荐

仓库地址: https://github.com/wang-xinyu/tensorrtx

看图可知,也就是通过c++源代码直接调用 TensorRT API ,对每个不同的网络模型进行重写,再调用 TensorRT Builder 生成 TensorRT Engine

1.使用作者定义的gen_wts.py的存储权重。 2.使用C++硬代码调用TensorRT C++API构建模型,加载gen_wts.py产生的权重组成完整模型。

1.可以控制每个layer的细节和权重,直接面对TensorRT API。 2.这种方案不存在算子问题,如果存在不支持的算子可以自行增加插件。

1.新模型需要对每个layer重写C++代码。 2.过于灵活,需要控制的细节多,技能要求很高。 3.部署时无法查看网络结构进行分析和排查。

为每个算子写Converter

仓库地址: https://github.com/NVIDIA-AI-IOT/torch2trt

1.作者为每一个算子(比如ReLU,Conv等),为每一个操醉的forward反射到自定义函数 2.通过反射torch的forward操作获取模块的权重,调用Python API接口实现模型

1.直接集成了Python、Pytorch,可以实现Pytorch模型到TensorRT模型的无缝转换。

1.提供了Python的方案并没有提供c++的方案。 2.新的算子需要自己实现converter,需要维护新的算子库 3.直接用Pytorch赚到tensorRT存储的模型是TensorRT模型,如果跨设备必须在设备上安装pytoch,灵活度差,不利于部署。 4.部署时无法查看网络结构进行分析和排查。

基于ONNX路线提供C++和Python的接口

仓库地址: https://github.com/shouxieai/tensorRT_Pro

通过Pytorch官方和NVIDIA官方对 torch->onnx onnx->TRT 算子库的支持。

1.集成工业级推理方案,支持TensorRT从模型导出到应用到项目中的全部工作 2.案例有YoloV5、YoloX、AlphaPose、RetinaFace、DeepSORT等,每个应用均为高性能工业级。 3.具有简单的模型导出方法和onnx问题的解决方案 4.具有简单的模型推理接口,封装tensorRT细节。支持插件。 5.依赖onnx,有两大官方进行维护。

onnx存在各种兼容性问题。

如何正确导出onnx(避坑指南)

  • 1.对于任何用到shape、size返回值的参数时,例如 tensor.view(tensor.size(0), -1) ,避免直接使用tensor.size的返回值,而是加上int转换, tensor.view(int(tensor.size(0)), -1) 。(这里的tensor值的是一个具体的张量)
  • 2.对于 nn.Upsample 或者 nn.fucntional.interpolate 函数,使用 scale_factor 指定倍率,而不是使用size参数指定大小。
  • 3.对于 reshape view 操作时,-1请指定到batch维度,其他维度计算出来即可。
  • 4. torch.onnx.export 指定 dynamic_axes 参数,并只指定batch维度,不指定其他维度。我们只需要动态batch,相对动态的宽高有其他方案。
  • 这些做法的必要性体现在简化过程的复杂度,去掉gather、shape类的节点。

    Example:

    import torch
    import torch.nn as nn
    class Model(nn.Module):
        def __init__(self):
            super().__init__()
            self.conv = nn.Conv2d(1, 1, 3, stride=1, padding=1, bias=True)
            self.conv.weight.data.fill_(0.3)
            self.conv.bias.data.fill_(0.2)
        def forward(self, x):
            x = self.conv(x)
            x.size(0)代表batch的大小
            x.numel()代表元素的数量
            那么int(x.numel() // x.size(0))就代表剩下维度的大小
            原则是batch的维度需要变为自动推理,这样可以实现动态batch的方案
            # return x.view(x.size(0), -1) 
            return x.view(-1, int(x.numel() // x.size(0)))
    model = Model().eval()
    x = torch.full((1, 1, 3, 3), 1.0)
    y = model(x)
    torch.onnx.export(
        model, (x, ), "model_name.onnx", verbose=True
    

    c++模型编译:

    /** 模型编译,onnx到trtmodel**/
    TRT::compile(
        TRT::Model::FP32,      /** 模式:fp32, fp16, int8 **/
        1,                     /** 最大batch size **/
        "model.onnx",          /** onnx文件 输入**/
        "model.fp32.trtmodel"  /** trt模型文件,输出 **/
    /** 加载编译好的引擎 **/
    auto infer = TRT::load_infer("model.fp32.trtmodel");
    /** 设置输入的值 **/
    infer->input(0)->set_to(1.0f);
    /** 引擎进行推理 **/
    infer->forward();
    /** 取出引擎的输出并打印 **/
    auto out = infer->output(0);
    for(int i = 0; i < out->channel(); ++i)
        INFO("%f", out->at<float>(0, i));
    
     
    推荐文章