• 【模型推理加速系列】06: 基于resnet18加速方案评测


    简介

    花雪随风不厌看,更多还肯失林峦。愁人正在书窗下,一片飞来一片寒。小伙伴们好,我是微信公众号小窗幽记机器学习的首席称重师:卖麻辣烫的小男孩。今天这篇文章以resnet18模型为例,对比Pytorch、ONNX、TorchScript、TensorRT模型格式在不同硬件(包括CPU和GPU)上的inference性能。由于此前TorchScript模型在 AMD CPU上的评测结果是负向效果(远慢于Pytorch),具体可以参考此前的推文模型推理加速系列|04:BERT模型推理加速 TorchScript vs. ONNX推理速度评测部分,因此本次实验涉及CPU评测部分改用Intel CPU

    本文也同步发布于微信公众号模型推理加速系列 | 06: 基于resnet18加速方案评测

    更多、更新文章欢迎关注微信公众号小窗幽记机器学习。后续会持续输出模型推理加速工程部署相关系列,敬请期待~

    老惯例,下图是算法生成的图片,仅供欣赏~

    在这里插入图片描述

    本次实验所用硬件信息如下:

    CPU:

    10  Intel(R) Xeon(R) Platinum 8255C CPU @ 2.50GHz
    
    • 1

    GPU:

    Nvidia T4 和 Nvidia 3090 都是单卡

    模型导出

    导出TorchScript

    关于如何导出TorchScript模型格式及其TorchScript模型格式的进一步介绍可以参考此前的文章:模型推理加速系列|04:BERT模型推理加速 TorchScript vs. ONNX
    模型推理加速系列|05:TorchScript模型格式简介及其使用。本文将 resnet18 导出TorchScript格式及其Python版inference的评测代码如下:

    #!/usr/bin/env python
    # -*- encoding: utf-8 -*-
    '''
    @File    :   check_jit.py
    @Time    :   2022/11/25 20:31:12
    @Author  :   卖麻辣烫的小男孩
    @Desc    :   
    '''
    import os
    os.environ['TORCH_HOME']='/data/model_zoo/cv'
    """
    默认情况下环境变量TORCH_HOME的值为~/.cache
    """
    
    import torch
    import torchvision
    import pdb
    import time
    from tqdm import tqdm
    import numpy as np
    
    
    def convert_resnet18_torchscript():
        """
        将 resnet18 转为 TorchScript 模型格式
        """
        # An instance of your model.
        model = torchvision.models.resnet18(pretrained=True)
    
        # Switch the model to eval model
        model.eval()
    
        # An example input you would normally provide to your model's forward() method.
        example = torch.rand(1, 3, 224, 224)
    
        # Use torch.jit.trace to generate a torch.jit.ScriptModule via tracing.
        trace_model = torch.jit.trace(model, example) # torch.jit.ScriptModule
    
        raw_output = model(example)
        trace_model_output = trace_model(example)
        np.testing.assert_allclose(raw_output.detach().numpy(), trace_model_output.detach().numpy())
        # Save the TorchScript model
        trace_model.save("/data/model_zoo/cv/resnet18_traced_model.pt")
    
    
        # Use torch.jit.trace to generate a torch.jit.ScriptModule via script.
        script_model = torch.jit.script(model)
        script_model_output = script_model(example)
        np.testing.assert_allclose(raw_output.detach().numpy(), script_model_output.detach().numpy())
        # Save the TorchScript model
        script_model.save("/data/model_zoo/cv/resnet18_script_model.pt")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    导出 ONNX

    关于如何导出ONNX模型格式可以参考之前的文章:模型推理加速系列|04:BERT模型推理加速 TorchScript vs. ONNX

    导出ONNX模型

    本次实验将resnet18导出为ONNX模型格式的代码如下:

    import torch
    
    MODEL_ONNX_PATH = "/data/model_zoo/cv/resnet18.onnx"
    OPERATOR_EXPORT_TYPE = torch._C._onnx.OperatorExportTypes.ONNX
    model = torchvision.models.resnet18(pretrained=True)
    model.eval()
    org_dummy_input = torch.rand(1, 3, 224, 224)
    torch.onnx.export(model,
                    org_dummy_input,
                    MODEL_ONNX_PATH,
                    verbose=True,
                    operator_export_type=OPERATOR_EXPORT_TYPE,
                    opset_version=12,
                    input_names=['inputs'],
                    output_names=['outputs'],
                    do_constant_folding=True,
                    dynamic_axes={"inputs": {0: "batch_size"}, "outputs": {0: "batch_size"}}
                    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    ONNX模型可视化

    利用 netron 对导出的ONNX模型进行可视化:

    netron  /data/model_zoo/cv/resnet18.onnx -p 8001 --host "0.0.0.0"
    
    • 1

    可视化结果如下:

    在这里插入图片描述

    导出TensorRT

    使用如下命令将 ONNX 格式模型转为 TensorRT 模型格式:

    CUDA_VISIBLE_DEVICES=0 trtexec --onnx=model_repo/resnet18.onnx  --minShapes=inputs:1x3x224x224 --optShapes=inputs:64x3x224x224 --maxShapes=input_ids:256x3x224x224 --saveEngine=model_repo/model.plan --workspace=20480
    
    • 1

    更多关于如何导出TensorRT模型格式的细节,敬请期待后续系列

    C++上做模型inference

    由于导出的 TorchScript 模型能够在C++上运行,本文进一步在C++上进行评测。

    编译和运行

    官方发布的LibTorch所有版本都是已经编译好的,解压后就可以使用。在Linux上提供了两种类型的libtorch二进制文件:一种是用GCC pre-cx11 ABI编译的,另一种是用GCC-cx11 ABI编译的,应该根据系统使用的GCC ABI进行选择。

    CMakeList.txt 内容如下:

    cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
    
    project(example-app)
    
    find_package(Torch REQUIRED)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}")
    
    add_executable(example-app example-app.cpp)
    target_link_libraries(example-app "${TORCH_LIBRARIES}")
    set_property(TARGET example-app PROPERTY CXX_STANDARD 14)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    cmake 编译:

    cmake -DCMAKE_PREFIX_PATH=/opt/conda/lib/python3.8/site-packages/torch/share/cmake/ ..
    cmake --build . --config Release
    
    • 1
    • 2

    运行程序:

    ./example-app /home/model_zoo/cv/resnet18_traced_model.pt gpu 1
    
    • 1

    功能测试

    torch::ones({1, 3, 224, 224}作为输入,测试结果如下。

    Python版GPU 上 inference的输出结果:

    (Pdb) outputs[0,:5]
    tensor([-0.0375,  0.1146, -1.7963, -1.2334, -0.8193], device='cuda:0',
           grad_fn=)
    
    • 1
    • 2
    • 3

    C++版CPU 上inference的输出结果:

    -0.0391  0.1145 -1.7968 -1.2343 -0.8190
    [ CPUFloatType{1,5} ]
    
    • 1
    • 2

    C++版GPU 上inference的输出结果:

    -0.0375  0.1146 -1.7963 -1.2334 -0.8193
    [ CUDAFloatType{1,5} ]
    
    • 1
    • 2

    评测结果

    以下综合评测了resnet18在原生Pytorch模型格式、ONNX、TorchScript(Python版和C++版)和TensorRT模型格式的inference性能。具体评测结果如下表所示(单位ms):

    CPU 版

    batch-sizePytorchONNXJIT-traceJIT-trace(C++)
    116.7714.414.3
    876.250.271.370.0
    16146.899.9139.6140.6
    32277.6194.3274269.9

    NVIDIA T4 GPU 评测结果:

    batch-sizePytorchONNXJIT-traceJIT-trace(C++)TensorRT
    14.24.14.24.23.9
    25.55.85.55.55.2
    49.58.39.59.58.4
    817.616.817.617.615.3
    1628.526.228.628.625.2
    325251.152.15250.7
    64100.396.2100.3100.292.6
    128显存不足198.6显存不足200174.8

    NVIDIA 3090 GPU 评测结果:

    batch-sizePytorchONNXJIT-traceJIT-trace(C++)TensorRT
    12.61.41.91.90.9
    22.71.51.921.1
    42.71.91.921.5
    82.72.72.32.32.4
    164.34.44.24.154.2
    327.67.87.57.57.3
    6414.113.813.91412.7
    12826.527.726.326.624

    小结

    本文基于resnet18模型在CPU和GPU上评测原生Pytorch模型格式、ONNX、TorchScript(Python版和C++版)和TensorRT模型格式的inference性能。根据上述评测结果可以得出以下初步结论:

    1. Intel CPU 上,ONNX推理速度最快

    2. 图片场景下(尺寸固定,只是batch size可变)如果使用GPU,TensorRT推理速度最快

    3. 小 batch size加速明显,随着batch size的增加,耗时近乎上线性增加,即提速收益不再增加

    4. 随着batch size的增加,各个方案的inference性能接近,没有显著差异。

    5. 相同模型格式不同编程语言在GPU上做推理,纯GPU inference部分耗时一样。不同语言在GPU上inference的差异仅仅在于把数据放在GPU上的API不同,最终是同一硬件GPU对同一模型进行inference,所需要的算力是一样的。

    6. C++中显存利用率更高

  • 相关阅读:
    Java中配置RabbitMQ基本步骤
    tomcat启动报错
    【Vue3】0-99
    yarn : 无法加载文件 C:\Users\sunlight\AppData\Roaming\npm\yarn.ps1,因为在此系统上禁止运行脚本。
    Kafka与Spring Boot等应用框架的集成及消息驱动模型
    SQL数据分析:sqlzoo官网学习select,where,order by,limit,聚合函数,having,常用函数,窗口函数,表链接,子查询
    Leecode-SQL 1393. 股票的资本损益
    PYTHON链家租房数据分析:岭回归、LASSO、随机森林、XGBOOST、KERAS神经网络、KMEANS聚类、地理可视化...
    竞赛 行人重识别(person reid) - 机器视觉 深度学习 opencv python
    ubuntu环境下载android源码
  • 原文地址:https://blog.csdn.net/ljp1919/article/details/128069501