PyTorch翻译官网教程-PROFILING YOUR PYTORCH MODULE

官网链接

Profiling your PyTorch Module — PyTorch Tutorials 2.0.1+cu117 documentation

分析pytorch模块

PyTorch包含一个分析器API,用于识别代码中各种PyTorch操作的时间和内存成本。分析器可以很容易地集成到代码中,结果可以作为表格打印或以JSON跟踪文件返回。

分析器支持多线程模型。分析器与主线程在同一个线程中运行,但它也会分析可能在另一个线程中运行的子线程。同时运行的分析器将被限制在它们自己的线程中,以防止混合结果。

PyTorch 1.8引入了新的API,将在未来的版本中取代旧的分析器API。在这个页面查看新的API(this page)。

在这个攻略中(this recipe),你可以更快速地了解Profiler API的用法。


import torch
import numpy as np
from torch import nn
import torch.autograd.profiler as profiler

使用分析器进行性能调试

分析器可以帮助识别模型中的性能瓶颈。在这个例子中,我们构建了一个自定义模块,它执行两个子任务:

  • 对输入进行线性变换
  • 使用转换结果来获得掩码张量上的索引。

我们使用profiler.record_function("label")将每个子任务的代码包装在单独的带标签的上下文管理器中。在分析器的输出中,子任务中所有操作的综合性能指标将显示在相应的标签下。

注意,使用分析器会带来一些开销,所以最好只在检查代码时使用。如果您要对运行时进行基准测试,请记住删除它。

class MyModule(nn.Module):def __init__(self, in_features: int, out_features: int, bias: bool = True):super(MyModule, self).__init__()self.linear = nn.Linear(in_features, out_features, bias)def forward(self, input, mask):with profiler.record_function("LINEAR PASS"):out = self.linear(input)with profiler.record_function("MASK INDICES"):threshold = out.sum(axis=1).mean().item()hi_idx = np.argwhere(mask.cpu().numpy() > threshold)hi_idx = torch.from_numpy(hi_idx).cuda()return out, hi_idx

分析forward执行

我们初始化随机输入和掩码张量以及模型。

在我们运行分析器之前,我们热身CUDA以确保准确的性能基准测试。我们将模块的正向传递封装在描述profiler.profile上下文管理器中。with_stack=True参数在跟踪中附加操作的文件和行号。

with_stack=True会带来额外的开销,更适合研究代码。如果您要对性能进行基准测试,请记住删除它。

model = MyModule(500, 10).cuda()
input = torch.rand(128, 500).cuda()
mask = torch.rand((500, 500, 500), dtype=torch.double).cuda()# warm-up
model(input, mask)with profiler.profile(with_stack=True, profile_memory=True) as prof:out, idx = model(input, mask)

打印分析器结果

最后,我们打印分析器的结果。profiler.key_averages 按操作符名称、输入形状和/或堆栈跟踪事件聚合结果。按输入形状分组对于识别模型使用哪些张量形状是有用的。

在这里,我们使用group_by_stack_n=5,它根据操作及其回溯(截断为最近的5个事件)汇总运行时间,并按注册的顺序显示事件。也可以通过传递sort_by参数对表进行排序(有关有效的排序键,请参阅文档docs )。

在notebook上运行分析器时,你可能会在堆栈跟踪中看到类似<ipython-input-18-193a910735e8>(13): forward的条目,而不是文件名。这些对应于<notebook-cell>(line number): calling-function.

print(prof.key_averages(group_by_stack_n=5).table(sort_by='self_cpu_time_total', row_limit=5))"""
(Some columns are omitted)-------------  ------------  ------------  ------------  ---------------------------------Name    Self CPU %      Self CPU  Self CPU Mem   Source Location
-------------  ------------  ------------  ------------  ---------------------------------MASK INDICES        87.88%        5.212s    -953.67 Mb  /mnt/xarfuse/.../torch/au<ipython-input-...>(10): forward/mnt/xarfuse/.../torch/nn<ipython-input-...>(9): <module>/mnt/xarfuse/.../IPython/aten::copy_        12.07%     715.848ms           0 b  <ipython-input-...>(12): forward/mnt/xarfuse/.../torch/nn<ipython-input-...>(9): <module>/mnt/xarfuse/.../IPython//mnt/xarfuse/.../IPython/LINEAR PASS         0.01%     350.151us         -20 b  /mnt/xarfuse/.../torch/au<ipython-input-...>(7): forward/mnt/xarfuse/.../torch/nn<ipython-input-...>(9): <module>/mnt/xarfuse/.../IPython/aten::addmm         0.00%     293.342us           0 b  /mnt/xarfuse/.../torch/nn/mnt/xarfuse/.../torch/nn/mnt/xarfuse/.../torch/nn<ipython-input-...>(8): forward/mnt/xarfuse/.../torch/nnaten::mean         0.00%     235.095us           0 b  <ipython-input-...>(11): forward/mnt/xarfuse/.../torch/nn<ipython-input-...>(9): <module>/mnt/xarfuse/.../IPython//mnt/xarfuse/.../IPython/-----------------------------  ------------  ---------- ----------------------------------
Self CPU time total: 5.931s"""

提高内存性能

请注意,就内存和时间而言,最昂贵的操作是掩码索引中的forward(10)操作。让我们首先尝试解决内存消耗问题。可以看到,第12行的。.to()操作消耗了953.67 Mb。该操作将mask复制到CPU。Mask用torch.double数据类型初始化。我们可以通过把它转换成torch.float来减少内存占用吗?

model = MyModule(500, 10).cuda()
input = torch.rand(128, 500).cuda()
mask = torch.rand((500, 500, 500), dtype=torch.float).cuda()# warm-up
model(input, mask)with profiler.profile(with_stack=True, profile_memory=True) as prof:out, idx = model(input, mask)print(prof.key_averages(group_by_stack_n=5).table(sort_by='self_cpu_time_total', row_limit=5))"""
(Some columns are omitted)-----------------  ------------  ------------  ------------  --------------------------------Name    Self CPU %      Self CPU  Self CPU Mem   Source Location
-----------------  ------------  ------------  ------------  --------------------------------MASK INDICES        93.61%        5.006s    -476.84 Mb  /mnt/xarfuse/.../torch/au<ipython-input-...>(10): forward/mnt/xarfuse/  /torch/nn<ipython-input-...>(9): <module>/mnt/xarfuse/.../IPython/aten::copy_         6.34%     338.759ms           0 b  <ipython-input-...>(12): forward/mnt/xarfuse/.../torch/nn<ipython-input-...>(9): <module>/mnt/xarfuse/.../IPython//mnt/xarfuse/.../IPython/aten::as_strided         0.01%     281.808us           0 b  <ipython-input-...>(11): forward/mnt/xarfuse/.../torch/nn<ipython-input-...>(9): <module>/mnt/xarfuse/.../IPython//mnt/xarfuse/.../IPython/aten::addmm         0.01%     275.721us           0 b  /mnt/xarfuse/.../torch/nn/mnt/xarfuse/.../torch/nn/mnt/xarfuse/.../torch/nn<ipython-input-...>(8): forward/mnt/xarfuse/.../torch/nnaten::_local        0.01%     268.650us           0 b  <ipython-input-...>(11): forward_scalar_dense                                          /mnt/xarfuse/.../torch/nn<ipython-input-...>(9): <module>/mnt/xarfuse/.../IPython//mnt/xarfuse/.../IPython/-----------------  ------------  ------------  ------------  --------------------------------
Self CPU time total: 5.347s"""

该操作的CPU内存占用减少了一半。

提高时间性能

虽然消耗的时间也减少了一些,但仍然太高了。事实证明,将矩阵从CUDA复制到CPU是非常昂贵的。forward (12)中的aten::copy_运算符将mask复制到CPU,这样CPU就可以使用NumPy中的argwhere函数。forward(13) 中的aten::copy_ 将数组作为张量复制回CUDA。如果我们在这里使用torch函数nonzero(),就可以消除这两个问题。

class MyModule(nn.Module):def __init__(self, in_features: int, out_features: int, bias: bool = True):super(MyModule, self).__init__()self.linear = nn.Linear(in_features, out_features, bias)def forward(self, input, mask):with profiler.record_function("LINEAR PASS"):out = self.linear(input)with profiler.record_function("MASK INDICES"):threshold = out.sum(axis=1).mean()hi_idx = (mask > threshold).nonzero(as_tuple=True)return out, hi_idxmodel = MyModule(500, 10).cuda()
input = torch.rand(128, 500).cuda()
mask = torch.rand((500, 500, 500), dtype=torch.float).cuda()# warm-up
model(input, mask)with profiler.profile(with_stack=True, profile_memory=True) as prof:out, idx = model(input, mask)print(prof.key_averages(group_by_stack_n=5).table(sort_by='self_cpu_time_total', row_limit=5))"""
(Some columns are omitted)--------------  ------------  ------------  ------------  ---------------------------------Name    Self CPU %      Self CPU  Self CPU Mem   Source Location
--------------  ------------  ------------  ------------  ---------------------------------aten::gt        57.17%     129.089ms           0 b  <ipython-input-...>(12): forward/mnt/xarfuse/.../torch/nn<ipython-input-...>(25): <module>/mnt/xarfuse/.../IPython//mnt/xarfuse/.../IPython/aten::nonzero        37.38%      84.402ms           0 b  <ipython-input-...>(12): forward/mnt/xarfuse/.../torch/nn<ipython-input-...>(25): <module>/mnt/xarfuse/.../IPython//mnt/xarfuse/.../IPython/INDEX SCORE         3.32%       7.491ms    -119.21 Mb  /mnt/xarfuse/.../torch/au<ipython-input-...>(10): forward/mnt/xarfuse/.../torch/nn<ipython-input-...>(25): <module>/mnt/xarfuse/.../IPython/aten::as_strided         0.20%    441.587us          0 b  <ipython-input-...>(12): forward/mnt/xarfuse/.../torch/nn<ipython-input-...>(25): <module>/mnt/xarfuse/.../IPython//mnt/xarfuse/.../IPython/aten::nonzero_numpy             0.18%     395.602us           0 b  <ipython-input-...>(12): forward/mnt/xarfuse/.../torch/nn<ipython-input-...>(25): <module>/mnt/xarfuse/.../IPython//mnt/xarfuse/.../IPython/
--------------  ------------  ------------  ------------  ---------------------------------
Self CPU time total: 225.801ms"""

扩展阅读

我们已经看到了如何在PyTorch模型中使用分析器来调查时间和内存瓶颈。在这里关于Profiler的信息:

  • Profiler Usage Recipe
  • Profiling RPC-Based Workloads
  • Profiler API Docs

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

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

相关文章

Integer中缓存池讲解

文章目录 一、简介二、实现原理三、修改缓存范围 一、简介 Integer缓存池是一种优化技术&#xff0c;用于提高整数对象的重用和性能。在Java中&#xff0c;对于整数值在 -128 到 127 之间的整数对象&#xff0c;会被放入缓存池中&#xff0c;以便重复使用。这是因为在这个范围…

爬虫百度返回“百度安全验证”终极解决方案

这篇文章也可以在我的博客查看 爬不了啊&#xff01;&#xff01; 最近一哥们跟我说百度爬虫爬不了 弹出&#xff1a;“百度安全验证”&#xff0c;“网络不给力&#xff0c;请稍后重试” 说到爬虫&#xff0c;这里指的是Python中最常用的requests库 我说怎么爬不了了&#x…

Python绘制爱心代码(七夕限定版)

写在前面&#xff1a; 又到了一年一度的七夕节啦&#xff01;你还在发愁送女朋友什么礼物&#xff0c;不知道怎样表达你满满的爱意吗&#xff1f;别担心&#xff0c;我来帮你&#xff01;今天&#xff0c;我将教你使用Python绘制一个跳动的爱心&#xff0c;用创意和幽默为这个…

Angular安全专辑之二——‘unsafe-eval’不是以下内容安全策略中允许的脚本源

一&#xff1a;错误出现 这个错误的意思是&#xff0c;拒绝将字符串评估为 JavaScript&#xff0c;因为‘unsafe-eval’不是以下内容安全策略中允许的脚本源。 二&#xff1a;错误场景 testEval() {const data eval("var sum2 new Function(a, b, return a b); sum2(em…

JavaWeb_LeadNews_Day6-Kafka

JavaWeb_LeadNews_Day6-Kafka Kafka概述安装配置kafka入门kafka高可用方案kafka详解生产者同步异步发送消息生产者参数配置消费者同步异步提交偏移量 SpringBoot集成kafka 自媒体文章上下架实现思路具体实现 来源Gitee Kafka 概述 对比 选择 介绍 producer: 发布消息的对象称…

寻路算法小游戏

寻路算法小demo 寻路算法有两种&#xff0c;一种是dfs 深度优先算法&#xff0c;一种是 dfs 深度优先算法 深度优先搜索的步骤分为 1.递归下去 2.回溯上来。顾名思义&#xff0c;深度优先&#xff0c;则是以深度为准则&#xff0c;先一条路走到底&#xff0c;直到达到目标。这…

矩形重叠问题

矩形重叠 文章目录 题目描述解题思路方法一方法二 题目描述 矩形以列表 [x1, y1, x2, y2] 的形式表示&#xff0c;其中 (x1, y1) 为左下角的坐标&#xff0c;(x2, y2) 是右上角的坐标。矩形的上下边平行于 x 轴&#xff0c;左右边平行于 y 轴。 如果相交的面积为 正 &#xff0…

Hadoop小结(下)

HDFS 集群 HDFS 集群是建立在 Hadoop 集群之上的&#xff0c;由于 HDFS 是 Hadoop 最主要的守护进程&#xff0c;所以 HDFS 集群的配置过程是 Hadoop 集群配置过程的代表。 使用 Docker 可以更加方便地、高效地构建出一个集群环境。 每台计算机中的配置 Hadoop 如何配置集群…

2023-08-19力扣每日一题-水题/位运算解法

链接&#xff1a; 2235. 两整数相加 题意&#xff1a; ab 解&#xff1a; ab 补一个位运算写法&#xff0c;进位是(a&b)<<1&#xff0c;不进位的计算结果为a^b 实际代码&#xff1a; #include<iostream> using namespace std; int sum(int num1, int n…

linux tomcat server.xml 项目访问路径变更不生效

如果想改成默认的127.0.0.1:8080 访问项目 先确定更改的作用文件 server.xml 的 host:appBase 标签 默认找到appBase webapps 下的war包&#xff0c;并解压&#xff0c;解压后的appname为访问路径 也就变成了 127.0.0.1:8080/appname host:Context:path 标签 appBase的 优先…

vue2和vue3

1. 双向数据绑定原理发生了改变 vue2的双向数据绑定是利用了es5 的一个API Object.definepropert() 对数据进行劫持 结合发布订阅模式来实现的。vue3中使用了es6的proxyAPI对数据进行处理。 相比与vue2&#xff0c;使用proxy API 优势有&#xff1a;defineProperty只能监听某个…

【OpenCV CMake find_packages找不到包】

根据OpenCV和各大网站提供的基于CMake的find_packages方法总是提示如下两种错误。 错误1&#xff1a;找不到OpenCV CMake Error at CMakeLists.txt:39 (find_package):By not providing "FindOpenCV.cmake" in CMAKE_MODULE_PATH this project hasasked CMake to fi…

深入探索:Kali Linux 网络安全之旅

目录 前言 访问官方网站 导航到下载页面 启动后界面操作 前言 "Kali" 可能指的是 Kali Linux&#xff0c;它是一种基于 Debian 的 Linux 发行版&#xff0c;专门用于渗透测试、网络安全评估、数字取证和相关的安全任务。Kali Linux 旨在提供一系列用于测试网络和…

菜鸟Vue教程 - 实现带国际化的注册登陆页面

初接触vue的时候觉得vue好难&#xff0c;因为项目中要用到&#xff0c;就硬着头皮上&#xff0c;慢慢的发现也不难&#xff0c;无外乎画个布局&#xff0c;然后通过样式调整界面。在通过属性和方法跟js交互。js就和我们写的java代码差不多了&#xff0c;复杂一点的就是引用这种…

Python数据分析实战-多线程并发处理列表(附源码和实现效果)

实现功能 Python数据分析实战-多线程并发处理列表 实现代码 import threading有15个列表&#xff0c;尝试多进程并发处理&#xff0c;每个列表一个进程&#xff0c;进程数和 CPU 核数一致def sum_list(lst):return sum(lst)if __name__ __main__:lists [[1,2,3], [4,5,6], …

BDA初级分析——SQL清洗和整理数据

一、数据处理 数据处理之类型转换 字符格式与数值格式存储的数据&#xff0c;同样是进行大小排序&#xff0c; 会有什么区别&#xff1f; 以rev为例&#xff0c;看看字符格式与数值格式存储时&#xff0c;排序会有什么区别&#xff1f; 用cast as转换为字符后进行排序 SEL…

解决element的select组件创建新的选项可多选且opitions数据源中有数据的情况下,回车不能自动选中创建的问题

前言 最近开发项目使用element-plus库内的select组件&#xff0c;其中有提供一个创建新的选项的用法&#xff0c;但是发现一些小问题&#xff0c;在此记录 版本 “element-plus”: “^2.3.9”, “vue”: “^3.3.4”, 问题 1、在options数据源中无数据的时候&#xff0c;在输入框…

spring boot 提示:程序包不存在,解决方法总结

背景&#xff1a; 之前出现过这样的问题&#xff0c;打包安装父项目就好了&#xff0c;今天改了一下代码&#xff0c;重新编译的时候&#xff0c;又出现了这样的情况&#xff0c;决定深度挖掘一下这里面的问题 spring boot 提示&#xff1a;程序包不存在&#xff0c;解决方法总…

mysql+jdbc+servlet+java实现的学生在校疫情信息打卡系统

摘 要 I Abstract II 主 要 符 号 表 i 1 绪论 1 1.1 研究背景 1 1.2 研究目的与意义 2 1.3 国内外的研究情况 2 1.4 研究内容 2 2 系统的开发方法和关键技术 4 2.1 开发方法 4 2.1.1 结构化开发方法 4 2.1.2 面向对象方法 4 2.2 开发技术 4 2.2.1 小程序开发MINA框架 4 2.2.2 …

快速搭建图书商城小程序的简易流程与优势

很多人喜欢阅读电子书&#xff0c;又有很多人依旧喜欢实体书&#xff0c;而实体书店拥有一个图书商城小程序便成为了满足用户需求的理想选择。如果您也想进入这一充满潜力的领域&#xff0c;但担心开发难度和复杂流程&#xff0c;别担心&#xff01;您能做到快速搭建一个专业、…