一行代码加速Pytorch推理速度6倍

news2024/11/29 20:49:19

一行代码加速Pytorch推理速度6倍

Torch-TensorRT 是 PyTorch 的集成,它利用 NVIDIA GPU 上的 TensorRT 推理优化。 只需一行代码,它就提供了一个简单的 API,可在 NVIDIA GPU 上提供高达 6 倍的性能加速。

话不多说, 线上代码, 再解释原理!!

文章目录

  • 一行代码加速Pytorch推理速度6倍
    • 学习目标
    • 内容
    • 1. 安装
    • 2. ResNet-50 概述
      • 模型说明
    • 3. 在没有优化的情况下运行模型
    • 4. 利用Torch-TensorRT进行加速
      • FP32 (single precision)
      • FP16 (half precision)
    • 5. 总结
    • Torch-TensorRT 如何工作
      • 简化 TorchScript 模块
      • 转换
      • 执行

学习目标

本笔记本演示了在预训练的 ResNet-50 网络上使用 Torch-TensorRT 编译 TorchScript 模块并运行它以测试获得的加速的步骤。

内容

  1. 安装
  2. ResNet-50 概述
  3. 在没有优化的情况下运行模型
  4. 使用 Torch-TensorRT 加速
  5. 结论

1. 安装

NVIDIA 的 NGC 提供 PyTorch Docker Container,其中包含 PyTorch 和 Torch-TensorRT。 我们可以使用 最新的 pytorch容器来运行这个notebook。

2. ResNet-50 概述

PyTorch 有一个名为 PyTorch Hub 的模型存储库,它是常见模型的高质量实现的来源。 我们可以从那里获得在 ImageNet 上预训练的 ResNet-50 模型。

模型说明

这个 ResNet-50 模型基于 Deep Residual Learning for Image Recognition 论文,该论文将 ResNet 描述为“一种使用单一深度残差检测图像中对象的方法” 神经网络”。输入大小固定为 32x32。

alt

3. 在没有优化的情况下运行模型

import torch
import torchvision

torch.hub._validate_not_a_forked_repo=lambda a,b,c: True

resnet50_model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet50', pretrained=True)
resnet50_model.eval()

加载我们的模型后,让我们继续下载一些图像!

!mkdir -p ./data
!wget  -O ./data/img0.JPG "https://d17fnq9dkz9hgj.cloudfront.net/breed-uploads/2018/08/siberian-husky-detail.jpg?bust=1535566590&width=630"
!wget  -O ./data/img1.JPG "https://www.hakaimagazine.com/wp-content/uploads/header-gulf-birds.jpg"
!wget  -O ./data/img2.JPG "https://www.artis.nl/media/filer_public_thumbnails/filer_public/00/f1/00f1b6db-fbed-4fef-9ab0-84e944ff11f8/chimpansee_amber_r_1920x1080.jpg__1920x1080_q85_subject_location-923%2C365_subsampling-2.jpg"
!wget  -O ./data/img3.JPG "https://inaturalist-open-data.s3.amazonaws.com/photos/98797/large.jpg"

!wget  -O ./data/imagenet_class_index.json "https://s3.amazonaws.com/deep-learning-models/image-models/imagenet_class_index.json"

所有预训练模型都期望输入图像以相同的方式归一化,
即形状为(3 x H x W)的 3 通道 RGB 图像,其中HW预计至少为224
图像必须加载到“[0, 1]”范围内,然后使用mean = [0.485, 0.456, 0.406]std = [0.229, 0.224, 0.225]进行归一化

这是一个示例。

from PIL import Image
from torchvision import transforms
import matplotlib.pyplot as plt
import json 

fig, axes = plt.subplots(nrows=2, ncols=2)

for i in range(4):
    img_path = './data/img%d.JPG'%i
    img = Image.open(img_path)
    preprocess = transforms.Compose([
        transforms.Resize(256),
        transforms.CenterCrop(224),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
    ])
    input_tensor = preprocess(img)      
    plt.subplot(2,2,i+1)
    plt.imshow(img)
    plt.axis('off')

# loading labels    
with open("./data/imagenet_class_index.json") as json_file: 
    d = json.load(json_file)

在本教程中,我们将使用一些实用函数; rn50_preprocess 用于预处理输入图像,predict 用于使用模型进行预测,benchmark 用于对推理进行基准测试。 您无需了解这些函数, 通过这些实用函数即可使用 Torch TensorRT.


import numpy as np
import time
import torch.backends.cudnn as cudnn
cudnn.benchmark = True

def rn50_preprocess():
    preprocess = transforms.Compose([
        transforms.Resize(256),
        transforms.CenterCrop(224),
        transforms.ToTensor(),
        transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
    ])
    return preprocess

# decode the results into ([predicted class, description], probability)
def predict(img_path, model):
    img = Image.open(img_path)
    preprocess = rn50_preprocess()
    input_tensor = preprocess(img)
    input_batch = input_tensor.unsqueeze(0) # create a mini-batch as expected by the model
    
    # move the input and model to GPU for speed if available
    if torch.cuda.is_available():
        input_batch = input_batch.to('cuda')
        model.to('cuda')

    with torch.no_grad():
        output = model(input_batch)
        # Tensor of shape 1000, with confidence scores over Imagenet's 1000 classes
        sm_output = torch.nn.functional.softmax(output[0], dim=0)
        
    ind = torch.argmax(sm_output)
    return d[str(ind.item())], sm_output[ind] #([predicted class, description], probability)

def benchmark(model, input_shape=(1024, 1, 224, 224), dtype='fp32', nwarmup=50, nruns=10000):
    input_data = torch.randn(input_shape)
    input_data = input_data.to("cuda")
    if dtype=='fp16':
        input_data = input_data.half()
        
    print("Warm up ...")
    with torch.no_grad():
        for _ in range(nwarmup):
            features = model(input_data)
    torch.cuda.synchronize()
    print("Start timing ...")
    timings = []
    with torch.no_grad():
        for i in range(1, nruns+1):
            start_time = time.time()
            features = model(input_data)
            torch.cuda.synchronize()
            end_time = time.time()
            timings.append(end_time - start_time)
            if i%10==0:
                print('Iteration %d/%d, ave batch time %.2f ms'%(i, nruns, np.mean(timings)*1000))

    print("Input shape:", input_data.size())
    print("Output features size:", features.size())
    print('Average batch time: %.2f ms'%(np.mean(timings)*1000))

下载模型并编写 util 函数后,让我们快速查看一些预测,并在当前未优化状态下对模型进行基准测试。

for i in range(4):
    img_path = './data/img%d.JPG'%i
    img = Image.open(img_path)
    
    pred, prob = predict(img_path, resnet50_model)
    print('{} - Predicted: {}, Probablility: {}'.format(img_path, pred, prob))

    plt.subplot(2,2,i+1)
    plt.imshow(img);
    plt.axis('off');
    plt.title(pred[1])

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xtm8OXSF-1673840883587)(1.png)]

# Model benchmark without Torch-TensorRT
model = resnet50_model.eval().to("cuda")
benchmark(model, input_shape=(128, 3, 224, 224), nruns=100)
Warm up ...
Start timing ...
Iteration 10/100, ave batch time 102.00 ms
Iteration 20/100, ave batch time 102.01 ms
Iteration 30/100, ave batch time 102.01 ms
Iteration 40/100, ave batch time 102.02 ms
Iteration 50/100, ave batch time 102.01 ms
Iteration 60/100, ave batch time 102.00 ms
Iteration 70/100, ave batch time 102.00 ms
Iteration 80/100, ave batch time 101.99 ms
Iteration 90/100, ave batch time 102.00 ms
Iteration 100/100, ave batch time 101.99 ms
Input shape: torch.Size([128, 3, 224, 224])
Output features size: torch.Size([128, 1000])
Average batch time: 101.99 ms

4. 利用Torch-TensorRT进行加速

继续下一步,使用 Torch TensorRT 加速。 在这些示例中,我们展示了 FP32(单精度)和 FP16(半精度)的结果。 我们不演示具体的调整,只是展示使用的简单性。 如果您想了解有关可能的自定义的更多信息,请访问我们的文档。

FP32 (single precision)

import torch_tensorrt

# The compiled module will have precision as specified by "op_precision".
# Here, it will have FP32 precision.
trt_model_fp32 = torch_tensorrt.compile(model, inputs = [torch_tensorrt.Input((128, 3, 224, 224), dtype=torch.float32)],
    enabled_precisions = torch.float32, # Run with FP32
    workspace_size = 1 << 22
)

继续运行benchmark

# Obtain the average time taken by a batch of input
benchmark(trt_model_fp32, input_shape=(128, 3, 224, 224), nruns=100)
Warm up ...
Start timing ...
Iteration 10/100, ave batch time 70.88 ms
Iteration 20/100, ave batch time 71.09 ms
Iteration 30/100, ave batch time 71.18 ms
Iteration 40/100, ave batch time 71.27 ms
Iteration 50/100, ave batch time 71.27 ms
Iteration 60/100, ave batch time 71.26 ms
Iteration 70/100, ave batch time 71.25 ms
Iteration 80/100, ave batch time 71.32 ms
Iteration 90/100, ave batch time 71.35 ms
Iteration 100/100, ave batch time 71.36 ms
Input shape: torch.Size([128, 3, 224, 224])
Output features size: torch.Size([128, 1000])
Average batch time: 71.36 ms

FP16 (half precision)

import torch_tensorrt

# The compiled module will have precision as specified by "op_precision".
# Here, it will have FP16 precision.
trt_model_fp16 = torch_tensorrt.compile(model, inputs = [torch_tensorrt.Input((128, 3, 224, 224), dtype=torch.half)],
    enabled_precisions = {torch.half}, # Run with FP16
    workspace_size = 1 << 22
)

继续运行benchmark

# Obtain the average time taken by a batch of input
benchmark(trt_model_fp16, input_shape=(128, 3, 224, 224), dtype='fp16', nruns=100)

Warm up ...
Start timing ...
Iteration 10/100, ave batch time 17.40 ms
Iteration 20/100, ave batch time 17.40 ms
Iteration 30/100, ave batch time 17.60 ms
Iteration 40/100, ave batch time 17.61 ms
Iteration 50/100, ave batch time 17.57 ms
Iteration 60/100, ave batch time 17.53 ms
Iteration 70/100, ave batch time 17.61 ms
Iteration 80/100, ave batch time 17.67 ms
Iteration 90/100, ave batch time 17.72 ms
Iteration 100/100, ave batch time 17.74 ms
Input shape: torch.Size([128, 3, 224, 224])
Output features size: torch.Size([128, 1000])
Average batch time: 17.74 ms

可以看到此处的平均时间是没有利用TensorRT优化的5.7倍左右

5. 总结

在本教程中,我们介绍了使用 Torch-TensorRT 为 ResNet-50 模型编译 TorchScript 模型的完整过程,并测试了优化对性能的影响。 使用 Torch-TensorRT,我们在 NVIDIA V100 GPU 上观察到 FP32 的加速为 1.42x,FP16 的加速为 5.4x。 这些加速数字会因 GPU 的不同而不同(以及基于所使用的操作的不同实施),我们鼓励您尝试最新一代的数据中心计算卡以获得最大加速。

现在是时候在您自己的模型上试用 Torch-TensorRT 了。 如果遇到任何问题,可以在 https://github.com/pytorch/TensorRT 上填写。 您的参与将有助于 Torch-TensorRT 的未来发展。

Torch-TensorRT 如何工作

Torch-TensorRT 作为 TorchScript 的扩展。 它优化并执行兼容的子图,让 PyTorch 执行剩余的图。 PyTorch 全面而灵活的功能集与 Torch-TensorRT 一起使用,解析模型并将优化应用于图的 TensorRT 兼容部分。

编译后,使用优化图就像运行一个 TorchScript 模块,用户可以获得更好的 TensorRT 性能。 Torch-TensorRT 编译器的架构由兼容子图的三个阶段组成:

  • 简化 TorchScript 模块
  • 转换
  • 执行

简化 TorchScript 模块

在第一阶段,Torch-TensorRT 简化了 TorchScript 模块,将常见操作的实现简化为更直接映射到 TensorRT 的表示。 需要注意的是,这种简化通道不会影响图形本身的功能。

转换

在转换阶段,Torch-TensorRT 会自动识别与 TensorRT 兼容的子图,并将其转换为 TensorRT 操作:

  • 具有静态值的节点被评估并映射到常量。
  • 描述张量计算的节点被转换为一个或多个 TensorRT 层。
  • 其余节点保留在 TorchScripting 中,形成一个混合图,作为标准 TorchScript 模块返回。

修改后的模块会通过嵌入的 TensorRT 引擎返回给您,这意味着整个模型(PyTorch 代码、模型权重和 TensorRT 引擎)可以在单个包中进行移植。

执行

当您执行已编译的模块时,Torch-TensorRT 会实时设置引擎并准备好执行。 当您执行这个修改后的 TorchScript 模块时,TorchScript 解释器会调用 TensorRT 引擎并传递所有输入。 引擎运行并将结果推送回解释器,就好像它是一个普通的 TorchScript 模块一样。

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

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

相关文章

【论文精读】Scaling distributed machine learning with the parameter server

Scaling distributed machine learning with the parameter server前言Abstract1. Introduction1.1 Contributions1.2 Engineering Challenges1.3 Related Work2. Machine Learning2.1 Goals2.2 Risk Minimization2.3 Generative Models3. Architecture3.1 (Key,Value) Vectors…

设计模式简要汇总

一、面向对象设计原则 开闭原则&#xff1a;一个软件实体&#xff08;类、模块、函数&#xff09;应该对扩展开放&#xff0c;对修改关闭。依赖倒置原则&#xff1a;高层模块不应该依赖底层模块&#xff0c;它们都应该依赖于抽象。抽象不应该依赖于细节&#xff0c;细节应该依…

语义分割——FCN模型pytorch实现

FCN网络简介 全卷积网络&#xff08;Fully Convolutional Networks&#xff0c;FCN&#xff09;是Jonathan Long等人于2015年在Fully Convolutional Networks for Semantic Segmentation一文中提出的用于图像语义分割的一种框架&#xff0c;是首个端对端的针对像素级预测的全卷…

BIGEMAP APP离线卫星地图数据应用

离线包&#xff08;高清卫星图&#xff09;&#xff1a; 1、一次下载永久可用&#xff0c;访问更快&#xff0c;下载更快 2、离线包数据可自动更新&#xff0c;无需重新下载&#xff0c;更新3到6个月一次 3、离线包可在无网络离线环境下使用&#xff0c;不受网络限制 4、离线包…

Springboot打成JAR包后读取配置文件

Springboot的默认配置文件为&#xff1a;application.properties或者是application.yml 如果这两个配置文件都存在&#xff0c;不冲突的话&#xff0c;就互相补充。冲突的话&#xff0c;则properties优先级高。 当我们使用IDEA创建出一个Springboot项目上时&#xff0c;配置文…

Git从入门到精通

目录 Git 配置 1. 在安装完成 Git 后&#xff0c;开始正式使用前&#xff0c;是需要有一些全局设置的&#xff0c;如用户名、邮箱。 2. 除了用户名、邮箱之外&#xff0c;还有很多的配置可以用来自定义 Git&#xff0c;如&#xff1a; 3. 查看所有的已经做出的配置&#xff…

Python3 常用内置函数解析(共28个函数)

文章目录一&#xff1a;Python3 操作符&#xff08;大全&#xff09;二&#xff1a;函数带括号与不带括号的区别三&#xff1a;不可变数据类型与可变数据类型四&#xff1a;Python3 内置函数&#xff08;大全&#xff09;1、input()&#xff1a;用于获取控制台的输入。2、print…

Django REST framework--渲染器

Django REST framework--渲染器Django REST framework--渲染器自定义接口规范渲染器基本原理Django 项目debug调试技巧异常信息处理配置异常处理模块自定义异常处理Django REST framework–渲染器 自定义接口规范 目前使用的是REST框架默认的返回格式&#xff0c;类似这种 […

【redis6】第十章(事务和锁机制)

Redis的事务定义 Redis事务是一个单独的隔离操作&#xff1a;事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中&#xff0c;不会被其他客户端发送来的命令请求所打断。 Redis事务的主要作用就是串联多个命令防止别的命令插队。 Multi、Exec、discard 从输入Mu…

2023年面试题之Dubbo基础架构

一. Dubbo 的整体架构设计有哪些分层?接口服务层&#xff08;Service&#xff09;&#xff1a;该层与业务逻辑相关&#xff0c;根据 provider 和 consumer 的业务设计对应的接口和实现配置层&#xff08;Config&#xff09;&#xff1a;对外配置接口&#xff0c;以 ServiceCon…

Docker 应用实践-镜像篇

一个 Docker 镜像往往是由多个镜像层&#xff08;可读层&#xff09;叠加而成&#xff0c;每个层仅包含了前一层的差异部分&#xff0c;单个镜像层也往往可以看作镜像使用&#xff0c;当我们启动一个容器的时候&#xff0c;Docker 会加载镜像层并在其上添加一个可写层。容器上所…

C语言学习——字符函数和字符串函数

&#x1f307;个人主页&#xff1a;平凡的小苏 &#x1f4da;学习格言&#xff1a;别人可以拷贝我的模式&#xff0c;但不能拷贝我不断往前的激情 &#x1f6f8;C语言专栏&#xff1a;https://blog.csdn.net/vhhhbb/category_12174730.html 小苏希望大家能从这篇文章中收获到许…

实战Kaggle比赛:预测房价

实战Kaggle比赛&#xff1a;预测房价 目录 下载和缓存数据集访问和读取数据集数据预处理训练K折交叉验证模型选择提交Kaggle预测 本节我们将通过Kaggle比赛&#xff0c;将所学知识付诸实践。 Kaggle的房价预测比赛是一个很好的起点。 此数据集由Bart de Cock于2011年收集 (D…

Linux--线程互斥与同步--0112 13

线程互斥 1.背景概念 临界资源&#xff1a;多线程执行流共享的资源就叫做临界资源。 临界区&#xff1a;每个线程内部&#xff0c;访问临界资源的代码就叫做临界区。 互斥&#xff1a;任何时刻&#xff0c;互斥保证有且只有一个执行流进入临界区 &#xff0c;对临界资源起保…

36岁北邮硕士,四段大厂经历,当初为了涨薪频繁跳槽,被裁后投遍所有公司,基本都不回复!...

今天给大家分享一位36岁北邮硕士的职场经历&#xff1a;2013年北邮硕士毕业后&#xff0c;分别在乐视、字节、阿里、小米待过&#xff0c;2022年被小米裁员&#xff0c;几乎投遍了boss上所有公司&#xff0c;基本都是已读不回。只有一个小公司的hr看了简历后回了一句“加油”。…

绕过某博客查看文章验证码,关注公众号得验证码

之前也写过一篇&#xff0c;当时使用Burpsuite抓包&#xff0c;改包&#xff0c;有点杀鸡用牛刀了。 虽然我挺支持为知识那啥的&#xff0c;但是吧要我去关注公众号太麻烦了 绕过查看文章需要验证码 其实就是改一个返回的字段&#xff0c;既然后端也是改&#xff0c;那我前端…

Google Earth Engine基础使用方法(一)

Google Earth Engine 1、注册账号1.1、设置谷歌账号辅助邮箱1.2、进入Google Earth Engine(如果第一次注册失败怎么办)1.3、进入Google Earth Engine Editor2、Editor主界面2.1、上传自己的矢量数据2.2、分享代码给别人2.3、保存代码2.4、几个有效快捷键2.5、搜索框有什么用3、…

SAP S/4 FAGLGVTR错误解决

本次年结支持过程中&#xff0c;一个客户的年结操作出现问题&#xff0c;问题的解决还颇费周折&#xff0c;稍稍记录一下。客户的SAP 版本是 S/4, 通过 FAA_CMP 事务码切换固定资产年度的时候&#xff0c;提示上一已关闭的会计年度与当前会计年度相同。 这个消息的意思是FI 的会…

【自学Python】Python字符串出现次数

Python字符串出现次数 Python字符串出现次数教程 在开发过程中&#xff0c;很多时候我们有统计单个字符或者 字符串 在另一个字符串中出现次数的需求&#xff0c;在 Python 中&#xff0c;统计字符串出现次数我们使用 count() 函数。 Python count()函数详解 语法 S.count…

Python实战项目1——自动获取小说工具

&#x1f935;‍♂️ 个人主页老虎也淘气 个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f44d;&#x1f3fb; 收藏…