如果我只有一个奔腾CPU,怎么加速推理神经网络?

news2024/9/27 19:24:28

前言

有人说当下的AI热潮不过是算力堆砌的产物。现在层出不穷的各种大模型大训练集,使用复杂精致的技术在排行榜上不断刷新分数,这些人似乎忘了一件事情,AI模型最终是要落地的,是要用的,如果不能普及开去那和在象牙塔中精心雕刻雕塑又有什么区别呢?尽管现在有不少简单易用的框架都支持硬件加速,但gpu高昂的成本和厂家自我研发的诸如NPU之类的框架复杂度依然存在。所以本文将以一个天真可爱的想法展开,如果我就是个穷鬼,掏不起钱买显卡,只有一个五年前的Intel低端cpu,但我也想玩时下流行的style transfer GAN,该怎么办?

环境

首先迎来本文的主角1号,我们的style transfer模型xxx.onnx:
处于隐私保护,这里不能透露主角的姓名,只能通过输入输出来管中窥豹捏。
在这里插入图片描述
可以看到输入是1,?,?,3,输出是?,?,?,3,我们确认这是个nhwc的输入,和onnx的标准输入形状ncwh是不一样的捏,据说这点会影响性能推理,但实测下来并没有。此外,?号表示动态输入,说明这个模型的输入输出都没有固定形状。如果你还是听不懂的话,就是图片进模型图片出模型捏,像下面这样:

原图:
在这里插入图片描述
生成图:
在这里插入图片描述
然后是本文主角2号,咱们高贵的奔腾cpu:
在这里插入图片描述

最后是本文主角3号:
python3.10.6
Onnxruntime1.14.0
在这里插入图片描述

加速

1.基准测试

import onnxruntime as ort
options = ort.SessionOptions()
options.enable_profiling = True #记录性能开关
result = session.run(None, {x: img})[0] #运行推理
prof_file = session.end_profiling() #推理结束后结束日志

首先我们需要对推理速度进行一个基本测试,在对代码进行多段time.time()插入计时后,如果我们需要具体看ONNX每层计算的时间,则需要使用它提供的profiling功能,方法很简单,先把开关打开然后在推理结束后终止记录,就会在同一目录下生成onnxruntime_profile_XXXX-XX-XX_XX-XX-XX.json文件。结果如下:
在这里插入图片描述
可以看到瓶颈就是在推理这里,用了9.37s,那么到底是什么算子会如此耗时呢?我们用以下代码查看json文件:

import json

with open('onnxruntime_profile__2023-03-02_10-23-47.json', "r") as f:
    sess_time = json.load(f)
l = sorted(sess_time, key=lambda k: k['dur'], reverse=True)
per = 0
total = l[0]['dur']
for x in l[2:52]:
    print(x['dur'])#打印持续时间
    print(x['args'])#打印具体参数
    per+=x['dur']
print(f'Top50 total is {per/total*100:.2f}%')

这段代码能打印前五十[2:52]最耗时间的算子,并且给出占比。需要注意的是前两个指的是总共时间,所以这里把它排除了,结果如下:

在这里插入图片描述
注意到无一例外全都是可恶的Conv层,卷积是真的耗时啊。

然后我们再跑一次,这次看看硬件使用率如何:
在这里插入图片描述
在卷积层这么耗时的情况下, cpu竟然在偷懒!

2.解决CPU偷懒的问题
在前面那段代码上继续加一个选项,把使用线程数调到4,我这个cpu是2核4线程,那就把它吃满!狠狠的用看看有没有提升:

options.intra_op_num_threads = 4

现在已经吃满了:

在这里插入图片描述
效果如下:

在这里插入图片描述

提升效果明显啊,提升了1s左右。9.3->7.7。

3.关闭ONNXRUNTIME本身的优化

options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_DISABLE_ALL

默认是全部开启优化的,我们把它关掉,发现性能反而提升了:

在这里插入图片描述
7.7->7.0,又快了0.7s。在经过后面GPU上的测试后发现该优化对gpu有一丁点的加速作用,对cpu来说反而是副作用。

4.固定尺寸+量化前预处理
这里假设我们已经对图片缩放到了1280x720分辨率。
先以1,720,1280,3的输入向量固定尺寸:

python -m onnxruntime.tools.make_dynamic_shape_fixed --input_name xxx --input_shape 1,720,1280,3

再进行量化前预处理,即尺寸推断和优化处理:

python -m onnxruntime.quantization.preprocess --input xxx.onnx --output xxx_preprocessed.onnx

再拿去跑一遍,发现又快了不少:
在这里插入图片描述
从7.0s快到了约6s,又提升1s。

总结

本例中,我们使用一些技巧成功使破烂cpu的推理速度加快了3s,得到了33%的性能提升,尽管提升看起来可能不够大,但在批量图片的生成过程中这就意味着节省几个小时。个人而言,我是非常希望所有的AI模型能以极低的代价和良好的性能为标准,推进AI模型的快速落地和普及,真正使一般大众都能玩起来,打破技术垄断。

备注

改变opset_version和量化也有可能提升性能,但在本例中均不明显,且量化后反而性能负提升。考虑到有人可能需要,在这里放两个链接:
改变opset_version
量化模型至int8

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

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

相关文章

2023年最新软著申请流程(一):软件著作权说明、国家版权官网的账号注册与实名认证

若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/129230460 红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软…

如何使用Cliam测试云端环境IAM权限安全

关于Cliam Cliam是一款针对云端安全的测试工具,在该工具的帮助下,广大研究人员可以轻松枚举目标云端环境的IAM权限。当前版本的Cliam支持下列云端环境:AWS、Azure、GCP和Oracle。 Cliam同时也是一个云端权限识别工具,该工具是一…

Mapper代理开发——书接MaBatis的简单使用

在这个mybatis的普通使用中依旧存在硬编码问题,虽然静态语句比原生jdbc都写更少了但是还是要写,Mapper就是用来解决原生方式中的硬编码还有简化后期执行SQL UserMapper是一个接口,里面有很多方法,都是一一和配置文件里面的sql语句的id名称所对…

HEC-HMS和HEC-RAS快速入门、防洪评价报告编制及洪水建模、洪水危险性评价等应用

目录 ①HEC-RAS一维、二维建模方法及实践技术应用 ②HEC-HMS水文模型实践技术应用 ③新导则下的防洪评价报告编制方法及洪水建模实践技术应用 ④基于ArcGIS水文分析、HEC-RAS模拟技术在洪水危险性及风险评估 ⑤山洪径流过程模拟及洪水危险性评价 ①HEC-RAS一维、二维建模方…

Torch同时训练多个模型

20230302 引言 在进行具体的研究时,利用Torch进行编程,考虑到是不是能够同时训练两个模型呢?!而且利用其中一个模型的输出来辅助另外一个模型进行学习。这一点,在我看来应该是很简单的,例如GAN网络同时训…

docker安装rabbitmq并挂载

1、拉取镜像 management:表示可以通过web页面管理。 alpine:表示是linux最小版本,不推荐新手安装。 docker pull rabbitmq:management2、创建用于挂载的目录 mkdir -p /mydata/rabbitmq/{data,conf,log} # 创建完成之后要对所创建文件授权…

从菜鸟程序员到高级架构师,竟然是因为这个字final

final实现原理 简介 final关键字,实际的含义就一句话,不可改变。什么是不可改变?就是初始化完成之后就不能再做任何的修改,修饰成员变量的时候,成员变量变成一个常数;修饰方法的时候,方法不允…

23种设计模式之简单工厂模式

一、场景简介 1、引入场景 订餐流程简单描述 食品抽象类,规定食品的基础属性操作 鱼类,鸡肉类食品类扩展 订餐流程类,根据食品名称,加工指定类型食品 模拟客户端预定操作 2、源代码实现 关系图谱 代码实现 /*** 简单工厂模式引入场景*/ public class C01_InScene { p…

【word】论文排版思路

1、 首先把所有中文的字体都按照要求改一下,记住都改成正文的字号和字体,后面再修改标题的,然后再改英文的,不要把顺序弄错了,不然得回头再改标题 然后定位文章里所有英文方法如下: 按CTRLF打开替换对话…

记录--虚拟滚动探索与封装

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 1. 介绍 什么是虚拟滚动?虚拟滚动就是通过js控制大列表中的dom创建与销毁,只创建可视区域dom,非可视区域的dom不创建。这样在渲染大列表中的数据时,只创…

快速生成QR码的方法:教你变成QR Code Master

目录 简介: 具体实现步骤: 一、可以使用Python中的qrcode和tkinter模块来生成QR码。以下是一个简单的例子,演示如何在Tkinter窗口中获取用户输入并使用qrcode生成QR码。 1)首先需要安装qrcode模块,可以使用以下命令在终端或命令…

aws batch 理解和使用batch进行批处理计算

文档 Compute Resource Memory ManagementRunning Workload on AWS Batch aws batch 是云上的批处理平台,通过托管环境减少了管理成本。包括配置大量计算资源,更具任务负载优化资源分配。 基本概念 job(任务),提交到…

C语言-结构体【详解】

一、 结构体的基础知识 结构是一些值的集合,这些值称为成员变量结构的每个成员可以是不同类型的变量 (1)结构体的声明 写法一: 注: 括号后边的分号不能忘结构体末尾可以不创建变量,在主函数中再创建 struc…

【ChatGPT】sqlachmey 多表连表查询语句

感受下科技带来的魅力,这篇文章是通过ChatGPT自动生成的,不得不说技术强大!!! 在SQLAlchemy中进行多表连接查询可以使用join()方法或join()函数,具体用法如下: join()方法 join()方法可以在SQLAlchemy ORM中的查询中使用。假设…

根据指定函数对DataFrame中各元素进行计算

【小白从小学Python、C、Java】【计算机等级考试500强双证书】【Python-数据分析】根据指定函数对DataFrame中各元素进行计算以下错误的一项是?import numpy as npimport pandas as pdmyDict{A:[1,2],B:[3,4]}myDfpd.DataFrame(myDict)print(【显示】myDf)print(myDf)print(【…

SMILES标准化方法以及其中的一个坑(手性)

rdkit.Chem.MolToSmiles()方法是用于将RDKit分子对象转换为SMILES字符串的方法。它的参数如下: mol:必需,要转换为SMILES字符串的RDKit分子对象。isomericSmiles:bool类型,是否生成同分异构体SMILES,默认为…

培训班出身的同学简历怎么做?面试要注意哪些?来自资深大厂HR的忠告

目录 1 不少培训班候选人的简历中,缺乏足够的商业项目年限 2 直接描述培训班学习经历会带来的负面影响 3 大龄转行Vs年轻的初级程序员,公司一般会如何选择? 4 经过培训班突击后,可以先面试小公司 5 面试官怎么面试有培训班经历…

安卓开发到底是做什么的

前言 在某平台看到了这样一个问题: 要知道,安卓开发是当前软件行业中的一个热门方向,它涉及到使用 Java 或 Kotlin 语言开发应用程序,运行在安卓操作系统上的手机、平板电脑、电视等设备上。在过去的几年中,随着智能…

追溯ChatGPT

ChatGPT 国内趋势 在国际学术界看来,ChatGPT / GPT-3.5 是一种划时代的产物 它与之前常见的语言模型 (Bert/ Bart/ T5) 的区别,几乎是导弹与弓箭的区别,一定要引起最高程度的重视 国际上的主流学术机构 (如斯坦福大学,伯克利加…

Ep_计网面试题-UDP实现TCP?

其实把TCP优点拿过来就行 直接上答案: 1、添加seq/ack机制,确保数据发送到对端 2、添加发送和接收缓冲区 3、添加超时重传机制 视频讲解: https://edu.csdn.net/course/detail/38090 点我进入 面试宝典 很多人不知道面试问什么,或者其他的XXGuide,那里边的太多没…