- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章有bug!用Pytorch Lightning重构代码速度更慢,修复后速度倍增由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
PyTorch Lightning 是一种重构 PyTorch 代码的工具,它可以抽出代码中复杂重复的部分,使得 AI 研究可扩展并且可以快速迭代。然而近日一位名为 Florian Ernst 的博主却发现 PyTorch Lightning 存在一个 bug——让原本应该加速的训练变得更慢了.
本文作者 Florian Ernst 。
Ernst 撰写博客详细描述了他发现这个 bug 的过程,以下是博客原文.
两周前,我将一些深度学习代码重构为 Pytorch Lightning,预计大约有 1.5 倍的加速。然而,训练、评估和测试任务的速度却降为原来的 1/4。重构之后的神经网络需要运行几天才能得出结果,因此我想找出原因,并尽可能地减少训练时间.
事情是这样的,我使用的是一些开源深度学习代码,这些代码是用来展示某些机器学习任务最新架构的。然而这些代码本身既不整洁也没进行优化。我注意到几个可以加速的地方,并将代码重构为 Pytorch 代码,让训练大约快了 3 倍.
但我认为还有改进的余地。Pytorch Lightning 是一个非常好的工具:它删除了大量样板代码,并配备了一些优化方法,因此我决定使用 Lightning 重构这些代码.
我原本希望代码大约能提速 1.5 倍,但完成重构时,我惊讶地发现迭代时间从 4 秒变成了 15 秒,这使训练时间多了近 3 倍.
问题出在哪里?
我首先运行 Lightning 的分析器来找出问题所在.
基础分析器给了我一个起点:大部分时间都花在运行一个 epoch 上;高级分析器没有给我更多信息.
我想知道我是否在神经网络上错误地配置了一些超参数。我打乱了其中一些超参数,训练速度没有任何变化.
然后我调整了数据加载器,发现改变作业数 n_jobs 会对总训练时间产生影响。然而影响不是加快了计算速度,而是减慢了.
随着 job 数变化,100 个 epoch 花费的时间.
使用 n_jobs=0 完全禁用多处理使我的迭代几乎比使用 6 个内核快了 2 倍。默认情况下,Pytorch 在两个 epoch 之间会 kill 掉运行中的进程(worker)并重新加载,因而需要重新加载数据集.
在我这个例子中,加载数据集非常慢。我将 DataLoader 里的 persistent_workers 参数设置为 True,以防止运行中的进程被杀死,进而防止重新加载数据.
因此,有两种可能性:
我在 GitHub 上创建了一个 issue,希望 Lightning 团队意识这个问题,接下来我要寻找问题根源.
GitHub 地址:https://github.com/PyTorchLightning/pytorch-lightning/issues/10389 。
Lightning 的 profiler 与上下文管理器一起运行并计算给定块花费的时间。它可以轻松搜索特定的 profiler 操作,以运行「run_training_epoch」为例 .
我开始探究 Lightning 源码,查看导致循环(loops)变慢的指令,我发现了一些问题:Loop.run 调用 Loop.on_run_start、Loop.on_run_start 重新加载 dataloader,如下图所示:
Loop.run 调用 Loop.on_run_start… 。
Loop.on_run_start 重新调用 dataloader 。
问题看起来确实来自在每个 epoch 中重新加载 DataLoader。查看 DataLoader 的源码,发现是这样的:
当使用 persistent_workers > 0 迭代 DataLoader 时,如果_iterator` 为 None,则使用_get_iterator() 重新加载整个数据集。可以确定的是 Pytorch Lightning 错误地重置了 _iterator,从而导致了这个问题.
为了证实这一发现,我用一个自定义的只能重载的__iter__方法替换了 DataLoader:
正如预期的那样,在迭代之后,_iterator 属性被正确设置,但在下一个 epoch 开始之前被重置为 None.
n_jobs=1,persistent_workers=True 。
现在,我只需要知道属性何时被设置为 None ,这样就可找到问题的根源。我尝试使用调试器,但由于多进程或 CUDA 而导致程序崩溃。我开始采用 Python 的 getter & setter 用法:
当 DataLoader._iterator 设置为 None 时,将会打印 stack trace 。
这样做非常有效,会输出如下内容:
通过跟踪发现每次开始运行时都会调用 DataLoader.reset。通过深入研究代码后,我发现每次迭代都会重置 DataFetcher,从而导致 DataLoader 也被重置。代码中没有条件来避免重置:每个 epoch 都必须重置 DataLoader.
这就是我发现迭代缓慢的根本原因.
既然发现了 bug,就要想办法修复。修复 bug 非常简单:我将 self.reset 行从 DataFetcher 的__iter__ 方法中移除:
通过修改后再次训练,现在一次迭代只需要 1.5 秒,而此前需要 15 秒,使用 vanilla Pytorch 也需要 3 秒,相比较而言,速度确实提升了很多.
我将发现的这个 bug 报告给了 Lightning 团队,他们对问题进行了修复并在第二天推送了修补程序。我随后更新了库,更新后发现他们的修复确实有效。相信更多人将从这次修复中受益,并且他们的 Lightning 模型的训练和测试时间会得到改善。如果你最近还没有更新依赖项,请尝试安装 pytorch-lightning==1.5.1 或更高版本! 。
原文链接:https://www.toutiao.com/a7034391328750371361/ 。
最后此篇关于有bug!用Pytorch Lightning重构代码速度更慢,修复后速度倍增的文章就讲到这里了,如果你想了解更多关于有bug!用Pytorch Lightning重构代码速度更慢,修复后速度倍增的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我在想出一个算法时遇到了麻烦... 我有一系列 GPS 数据,以 1 秒为间隔记录时间、速度、距离。假设距离是米,速度是米/秒。可能有超过 2 小时的数据,或 7200 个点。这里的“时间”字段主要是
使用java排序器,即: Collections.sort(myArrayList, new Comparator() { @Override public int c
有什么区别吗 SELECT * FROM my_table 和 SELECT my_column_id FROM my_table 地点: my_table 有百万行 网站上有大量并发用户进行sql查
有2个样本。 在第一个示例中,使用 orderby 可以更快地获得结果。 (根据 phpmyadmin 速度报告) 在另一个例子中,我没有使用 order by,它给出的结果较慢。 (根据 phpmy
我注意到,如果我将训练数据加载到内存中并将其作为 numpy 数组提供到图中,与使用相同大小的 shuffle 批次相比,速度会有很大差异,我的数据有大约 1000 个实例。 使用内存 1000 次迭
我在 python 中使用破折号。我正在绘制记录到 SQLite 数据库中的实时数据,目前,我正在绘制单个值与时间线图。我计划再添加 20 个图表,但目前,随着时间的增加, plotly 变慢,我认为
我试图调用 hasNext Velocity 模板中的方法,以便根据 foreach 循环中的位置影响行为 - 仅 hasNext没有按照文档工作。 这是 Velocity 用户指南的片段,关于 ha
在我正在制作的游戏中,我有两个点,pt1 和 pt2,我想计算出它们之间的角度。我已经在较早的计算中计算出距离。显而易见的方法是对垂直距离上的水平距离进行反正切 (tan(theta) = opp/a
我经常遇到字符串值不存在和/或为空的情况。这是测试这种情况的最佳方法吗? #if( $incentive.disclaimer && $!incentive.disclaimer != '' )
我想将一个模板nested包含在其他模板cont1,cont2和cont3中。 并且嵌套模板应仅对cont1隐藏一个特定控件。 在包含在cont1中之前,我想为一些标志变量$hideMyControl
是否可以更改从“Windows Azure Media Encoder”输出的音频的播放速度? 我正在使用配置为“WMA High Quality Audio”的“Windows Azure Medi
我使用速度将String(template)与字段合并 hi there I'am ${name}, And I'am ${age} old. velocity将字段${name}和${age}与一种
我使用的是 LockedBitmap 类,它简化了 C# 中位图数据的处理。目前它正在将数据复制到本地 byte[] 数组中,然后通过其类方法访问该数组以获取/设置像素颜色值。 这比直接通过指针访问锁
我尝试在 VM_global_library.vm 文件中添加一堆 #set($x=abc) 语句,但这些变量在我的 VM 模板中不可用。 我想为图像的基本路径等设置一个全局变量。这可能吗? 最佳答案
我的项目结构: -src --main ---java ----makers -----SomeClass ---resources ----htmlPattern.vm 如何告诉 SomeClass
我正在尝试从 Velocity 中的字符串中删除不需要的字符(换行符可以,但不能像 EM 和 CAN ASCII 控制字符那样)。 #set($cleanScreen = $cleanScreen.r
我想在日.月.年之间的点处分割日期。例如:2015 年 1 月 14 日至 {14, 01, 2015}这是我使用的代码:dates3.get(0) 包含我从页面的文本字段获取的字符串“14.01.2
之后,从 1.5 升级到速度引擎 1.7 出现了 1.5 没有的问题。为了解释这个问题,我必须展示一个代码片段: #foreach($someVariable in $someCollection)
我想知道从表中选择所有字段是否更快: SELECT * 或只选择您真正需要的: SELECT field1, field2, field3, field4, field5... 假设表有大约 10 个
我正在尝试模仿照片应用程序的行为,在该应用程序中,用户用手指平移照片并且照片具有一定的速度。由于我不会深入的原因,我不能将 UIScrollView 与它的缩放 UIImageView 一起使用,而是
我是一名优秀的程序员,十分优秀!