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

news2025/1/20 17:05:47

简介

花雪随风不厌看,更多还肯失林峦。愁人正在书窗下,一片飞来一片寒。小伙伴们好,我是微信公众号小窗幽记机器学习的首席称重师:卖麻辣烫的小男孩。今天这篇文章以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

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")

导出 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"}}
                )

ONNX模型可视化

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

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

可视化结果如下:

在这里插入图片描述

导出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

更多关于如何导出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)

cmake 编译:

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

运行程序:

./example-app /home/model_zoo/cv/resnet18_traced_model.pt gpu 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=<SliceBackward0>)

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

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

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

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

评测结果

以下综合评测了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++中显存利用率更高

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/40913.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

cmdline(二):uboot cmdline怎么传?cmdline kernel怎么用?

前面我们知道了cmdline是什么&#xff0c;已经在哪里添加cmdline&#xff1f;现在我们来看看在哪里传输cmdline&#xff0c;以及传输收到后怎么用&#xff1f; 参考内容来自前辈&#xff0c;感激&#xff1a; https://blog.csdn.net/weixin_42031299/article/details/12123950…

Spring Boot JPA EntityManager实体管理器示例

在本教程中&#xff0c;您将了解如何在 Spring Boot 示例中使用 JPA EntityManager&#xff08;使用 CRUD 操作和查询方法&#xff09;。我将向您展示&#xff1a; 在 Spring 引导中访问 JPA 实体管理器的方法如何使用实体管理器方法&#xff1a;执行SQL查询使用和CRUD操作cre…

【Android App】实现在线语音合成功能(使用云知声平台和WebSocket 超详细 附源码)

需要源码和Jar包请点赞关注收藏后评论区留下QQ~~~ 一、在线语音合成 虽然国产智能机大多集成了中文语音引擎&#xff0c;但是系统自带的语音工具无法满足商用要求&#xff0c;功能单一&#xff0c;所以势必引入第三方的语音引擎&#xff0c;依靠第三方提供的开发包统一支撑语音…

【新知实验室】——腾讯云音视频TRTC体验

腾讯实时音视频 TRTC 是什么&#xff1f; 腾讯实时音视频&#xff08;Tencent Real-Time Communication&#xff0c;TRTC&#xff09;将腾讯21年来在网络与音视频技术上的深度积累&#xff0c;以多人音视频通话和低延时互动直播两大场景化方案&#xff0c;通过腾讯云服务向开发…

clickHouse基础语法

clichouse数据类型 整形 lnt8 8bit,1字节 &#xff08;-128-127&#xff09;lnt16 16bitlnt32 32bitlnt64 64bit 无符号整型 相比于上面&#xff0c;就是把负数部分挪到正数部分 Ulnt8 &#xff08;0-255&#xff09;Ulnt16Ulnt32Ulnt64 浮点型 Float32 也就是floatFloa…

Instant Neural Graphics Primitives with a Multiresolution Hash Encoding以及源码浅析

背景 现存的一些新视图合成的训练过程和渲染速度都比较慢&#xff0c;其原因是因为query point需要使用MLP编码&#xff0c;而且在一个采样空间中&#xff0c;存在很多无效的query point也要计算其density和color&#xff0c;从而出现很多冗余计算。 作者针对这个问题&#x…

MAUI 中使用 DI 及 MVVM

MAUI 中使用 DI 及 MVVM为什么要使用 依赖注入 和 MVVM如何在 MAUI 中使用依赖注入如何使用 MVVM不使用框架或组件定义一个 BaseViewModelMainViewModel 的实现MainPage 中进行 Binding使用组件优化前面的 ViewModel 代码基项目的效果为什么要使用 依赖注入 和 MVVM MVVM 和 依…

1535_TriCore编译器Tasking使用_汇编分区、内置函数以及伪指令

全部学习汇总&#xff1a; GreyZhang/TriCore_Tasking_Compiler_Skills: Some skills for Tasking compiler on AURIX platform. Happy hacking! (github.com) 看了一下这个章节的内容&#xff0c;原本看着页数很多拆分成了两次学习。后面发现剩下的这部分内容主要并不是框架性…

项目实战——项目上线

ps : 项目要在云服务器上部署&#xff0c;博主自己是用的腾讯云&#xff0c;大家可以选择购买合适的服务器进行部署 目录 一、AC终端操 1、ssh登录服务器 2、创建新用户 3、分配用户 sudo 权限 4、配置免密登录&#xff08;SSH&#xff09; 5、传递祖传文件给服务器 6、安…

JetpackCompose从入门到实战学习笔记2——Modifier的简单使用

JetpackCompose从入门到实战学习笔记2——Modifier的简单使用 1.Image的使用&#xff1a; Composable fun Image(modifier: Modifier) {Row {Image(painterResource(id R.mipmap.iv_pic),contentDescription stringResource(R.string.description),modifier modifier.size…

阿里P8熬了一个月肝出这份32W字Java面试手册,传到Git上目前star数达到了30K+

互联网行业竞争越来越严峻&#xff0c;面试也是越来越难&#xff0c;一直以来我都想整理一套完美的面试宝典&#xff0c;奈何难抽出时间&#xff0c;这套1000道的Java面试手册我整理了整整1个月&#xff0c;上传到Git上目前star数达到了30K这套互联网Java工程师面试题包括了&am…

【iOS】UITableView的动态Cell高度(Masonry)

动态cell高度评论长度不同引出的问题实现评论长度不同引出的问题 对于之前写的项目的评论部分&#xff0c;由于评论文字字数的不同会导致label高度不同&#xff0c;所以需要设定不同的cell高度来展示。 一开始使用了 CGSize labelSize [label.text boundingRectWithSize:CG…

数据结构与算法_AVL平衡二叉树_四种旋转,插入和删除

1 AVL平衡二叉树的概念 平衡二叉树在BST树基础上加了平衡操作。 BST树特点 &#xff1a;在BST树的基础上&#xff0c;引入了节点“平衡”的概念&#xff0c;任意一个节点的左右子树高度差不超过 1 &#xff0c;为了维持节点的平衡&#xff0c;引入了四种旋转操作&#xff0c;如…

MySQL的时区引起的前后端数据交互不畅的问题解决

MySQL的时区问题 一、问题起源 在使用swagger2进行代码测试时&#xff0c;执行完成后显示的时间与国内时间少了8个小时 强迫症的原因&#xff0c;就手贱了如下操作 ① 修改MySQL内的时间 set global time_zone 8:00; flush privileges;② show variables like “%time_zone%…

整数除法不用除号

给定两个整数 a 和 b &#xff0c;求它们的除法的商 a/b &#xff0c;要求不得使用乘号 *、除号 / 以及求余符号 % 。 注意&#xff1a; 整数除法的结果应当截去&#xff08;truncate&#xff09;其小数部分&#xff0c;例如&#xff1a;truncate(8.345) 8 以及 truncate(-2…

【路径规划】(2) A* 算法求解最短路,附python完整代码

大家好&#xff0c;今天和各位分享一下机器人路径规划中非常经典的 A* 算法&#xff0c;感兴趣的点个关注&#xff0c;文末有 python 代码&#xff0c;那我么开始吧。 1. 算法介绍 A* 算法是 1968 年 P.E.Hart[1]等人所提出的在全局地图环境中所有已知情形下求解最短路径问题的…

部分gcc预定义宏和函数栈帧的内存分布

本文简单基于树莓派8&#xff0c;linux4.4.50版本&#xff0c;32位arm cpu 尝试了解函数调用栈的内存分布的形态。使用gcc内置的宏 __builtin_frame_address 来打印栈帧内存上的信息&#xff0c;以及了解一下常用的gcc 内置的宏的输出。 针对 __builtin_frame_address 在gcc官网…

猴子也能学会的jQuery第十二期——jQuery遍历(上)

&#x1f4da;系列文章—目录&#x1f525; 猴子也能学会的jQuery第一期——什么是jQuery 猴子也能学会的jQuery第二期——引用jQuery 猴子也能学会的jQuery第三期——使用jQuery 猴子也能学会的jQuery第四期——jQuery选择器大全 猴子也能学会的jQuery第五期——jQuery样式操作…

PIC单片机3——外部中断

//RB2&#xff08;INT2&#xff09;作为外中断 #include <p18cxxx.h>/*18F系列单片机头文件*/ void PIC18F_High_isr(void);/*中断服务函数声明*/ void PIC18F_Low_isr(void); #pragma code high_vector_section0x8 /*高优先级中断响应时&#xff0c;会自动跳转到0x8处…

基于三相坐标系状态方程的感应电动机起动动态计算matlab程序

基于三相坐标系状态方程的感应电动机起动动态计算matlab程序 1 异步电动机动态数学模型的性质 电磁耦合是机电能量转换的必要条件&#xff0c;电流与磁通的乘积产生转矩&#xff0c;转速与磁通的乘积得到感应电动势。无论是直流电动机&#xff0c;还是交流电动机均如此。 交、直…