PyTorch Profiler v1.9 已发布!此次新版本发布的目标(之前的PyTorch Profiler 版本)是为您提供最先进的新工具,无论您是在单机还是多机上工作,都能帮助您诊断和修复机器学习性能问题。其目标是找出耗时和/或耗内存最多的执行步骤,并可视化 GPU 和 CPU 之间的工作负载分布。
以下是本次发布的五项主要功能的摘要
- 分布式训练视图:这有助于您了解分布式训练作业中消耗的时间和内存。当您将训练模型分解为并行运行的工作节点时,可能会出现许多问题,因为它可能是一个黑盒。模型的总体目标是加快模型训练速度。此分布式训练视图将帮助您诊断和调试单个节点内的问题。
- 内存视图:此视图允许您更好地了解内存使用情况。此工具将通过在程序运行的各个点显示活动内存分配,帮助您避免臭名昭著的内存不足错误。
- GPU 利用率可视化:此工具可帮助您确保 GPU 得到充分利用。
- 云存储支持:Tensorboard 插件现在可以从 Azure Blob Storage、Amazon S3 和 Google Cloud Platform 读取分析数据。
- 跳转到源代码:此功能允许您可视化堆栈跟踪信息并直接跳转到源代码。这有助于您根据分析结果快速优化和迭代代码。
PyTorch 分析工具入门
PyTorch 包含一个名为“PyTorch Profiler”的分析功能。PyTorch Profiler 教程可在此处找到:此处。
要对 PyTorch 代码进行分析,您必须
$ pip install torch-tb-profiler
import torch.profiler as profiler
With profiler.profile(XXXX)
评论:
• 对于 CUDA 和 CPU 分析,请参见此处
with torch.profiler.profile(
activities=[
torch.profiler.ProfilerActivity.CPU,
torch.profiler.ProfilerActivity.CUDA],
• 使用 profiler.record_function("$NAME"):允许为函数块放置一个装饰器(与名称关联的标签)
• profiler.profile 下的 profile_memory=True 参数允许您分析 CPU 和 GPU 内存占用
使用 PyTorch Profiler 可视化 PyTorch 模型性能
分布式训练
深度学习的最新进展证明了大数据集和大型模型的价值,这要求您将模型训练扩展到更多的计算资源。分布式数据并行 (DDP) 和 NVIDIA 集合通信库 (NCCL) 是 PyTorch 中广泛采用的范例,用于加速深度学习训练。
在 PyTorch Profiler 的此版本中,现在支持带有 NCCL 后端的 DDP。

计算/通信概述
在分布式训练视图下的“计算/通信概述”中,您可以观察每个工作器和工作器之间的[负载均衡器](https://en.wikipedia.org/wiki/Load_balancing_(computing) 节点的计算与通信比率,该比率按粒度测量。
场景 1:
如果一个工作器的计算和重叠时间远大于其他工作器,这可能表明工作负载不平衡或工作器是拖沓者。计算是 GPU 上内核时间的总和减去重叠时间。重叠时间是通过在计算期间交错通信而节省的时间。重叠时间越多表示计算和通信之间的并行性越好。理想情况下,计算和通信完全重叠。通信是总通信时间减去重叠时间。下面的示例图像显示了此场景如何在 Tensorboard 上显示。

图:一个拖沓者示例
场景 2:
如果批处理大小很小(即每个工作器上的计算量较少)或要传输的数据很大,则计算与通信之比也可能很小,并且在分析器中表现为 GPU 利用率低和等待时间长。此计算/通信视图将允许您诊断代码,通过采用梯度累积来减少通信,或通过增加批处理大小来降低通信比例。DDP 通信时间取决于模型大小。批处理大小与模型大小无关。因此,增加批处理大小可以使计算时间更长,并使计算与通信之比更大。
同步/通信概述
在“同步/通信”视图中,您可以观察通信效率。这是通过将步长减去计算和通信时间来完成的。同步时间是等待和与其他工作器同步的总通信时间的一部分。“同步/通信”视图包括初始化、数据加载器、CPU 计算等。从该视图中可以得出诸如总通信中真正用于交换数据的比例以及等待来自其他工作器的数据的空闲时间等见解。

例如,如果存在效率低下的工作负载平衡或拖沓者问题,您将能够在此“同步/通信”视图中识别它。此视图将显示几个工作器的等待时间比其他工作器长。

上面的表格视图允许您查看每个节点中所有通信操作的详细统计信息。这允许您查看正在调用哪些操作类型、每个操作被调用了多少次、每个操作传输的数据大小等。
内存视图:
此内存视图工具可帮助您了解模型中操作符的硬件资源消耗。了解操作符级别的时间和内存消耗使您能够解决性能瓶颈,从而使模型执行更快。鉴于 GPU 内存大小有限,优化内存使用可以
- 允许更大的模型,这可能在最终任务中泛化得更好。
- 允许更大的批处理大小。更大的批处理大小会提高训练速度。
分析器会在分析器间隔期间记录所有内存分配。选择“设备”将允许您查看每个操作符在 GPU 侧或主机侧的内存使用情况。您必须启用profile_memory=True
才能生成如下所示的内存数据:此处。
With torch.profiler.profile(
Profiler_memory=True # this will take 1 – 2 minutes to complete.
)
重要定义:
• “大小增加”显示所有分配字节的总和减去所有内存释放字节。
• “分配大小”显示所有分配字节的总和,不考虑内存释放。
• “自我”表示分配的内存不是来自任何子操作符,而是由操作符本身分配的。

时间轴上的 GPU 指标:
当一个或多个 GPU 未充分利用时,此功能将帮助您调试性能问题。理想情况下,您的程序应具有高 GPU 利用率(目标为 100% GPU 利用率)、最小的 CPU 到 GPU 通信以及无开销。
概述:概述页面突出显示了三个重要 GPU 使用指标在不同级别(即 GPU 利用率、预估 SM 效率和预估实现占用率)的结果。本质上,每个 GPU 都有许多 SM,每个 SM 都有许多 warp,可以并发执行许多线程。Warp 执行的数量取决于 GPU。但从高层次来看,时间轴上的 GPU 指标工具允许您查看整个堆栈,这很有用。
如果 GPU 利用率结果较低,这表明您的模型中可能存在潜在瓶颈。常见原因包括
•内核并行度不足(即,批处理大小小)
•循环中调用的小内核。这意味着启动开销没有摊销
•CPU 或 I/O 瓶颈导致 GPU 未收到足够的工作以保持繁忙
查看概述页面,其中性能建议部分将提供有关如何提高 GPU 利用率的潜在建议。在此示例中,GPU 利用率较低,因此性能建议是增加批处理大小。根据性能建议,将批处理大小从 4 增加到 32,GPU 利用率提高了 60.68%。
GPU 利用率:分析器中 GPU 引擎执行工作负载的步长间隔时间。利用率百分比越高越好。仅使用 GPU 利用率诊断性能瓶颈的缺点是它过于高层和粗略。它无法告诉您有多少流多处理器正在使用。请注意,虽然此指标对于检测空闲时间很有用,但高值并不表示 GPU 的高效使用,仅表示它正在执行任何操作。例如,一个持续运行单个线程的内核将获得 100% 的 GPU 利用率。
估计流式多处理器效率 (Est. SM Efficiency) 是一个更细粒度的指标,它表示在跟踪中的任何时间点有多少百分比的 SM 正在使用,以及那些停滞的 SM(NVIDIA 文档)。Est. SM Efficiency 也有其局限性。例如,每个块只有一个线程的内核无法充分利用每个 SM。SM Efficiency 并不能告诉我们每个 SM 有多忙,只告诉我们它们正在做任何事情,这可能包括在等待内存加载结果时停滞。为了保持 SM 繁忙,有必要有足够数量的就绪 warp,以便在发生停滞时运行。
估计达到的占用率 (Est. Achieved Occupancy) 比 Est. SM Efficiency 和 GPU 利用率更深一层,用于诊断性能问题。估计达到的占用率表示每个 SM 可以同时有多少个活动 warp。拥有足够数量的活动 warp 通常是实现良好吞吐量的关键。与 GPU 利用率和 SM Efficiency 不同,其目标并非尽可能高。根据经验,将此指标提高到 15% 及以上可以获得良好的吞吐量增益。但在某个时候,您将遇到收益递减。例如,如果该值已经达到 30%,则进一步的增益将不确定。此指标报告内核执行期间所有 warp 调度程序的平均值(NVIDIA 文档)。Est. Achieved Occupancy 值越大越好。
概述详情:Resnet50_batchsize4
概述详情:Resnet50_batchsize32
内核视图 内核具有“每个 SM 的块数”和“预估实现占用率”,这是一个比较模型运行的绝佳工具。

每个 SM 的平均块数
每个 SM 的块数 = 此内核的块数 / 此 GPU 的 SM 数量。如果此数字小于 1,则表示 GPU 多处理器未充分利用。“每个 SM 的平均块数”是此内核名称所有运行的加权平均值,使用每次运行的持续时间作为权重。
平均预估实现占用率
预估实现占用率定义如概述中所示。“平均预估实现占用率”是此内核名称所有运行的加权平均值,使用每次运行的持续时间作为权重。
跟踪视图 此跟踪视图显示了一个时间轴,其中显示了模型中操作符的持续时间以及哪个系统执行了该操作。此视图可以帮助您确定高消耗和长时间执行是否是由于输入或模型训练造成的。目前,此跟踪视图在时间轴上显示 GPU 利用率和估计 SM 效率。

GPU 利用率独立计算并分为多个 10 毫秒桶。桶的 GPU 利用率值绘制在时间轴旁边,范围为 0-100%。在上面的示例中,线程 28022 繁忙期间的“ProfilerStep5”GPU 利用率高于其后的“Optimizer.step”。您可以在此处放大以调查其原因。

从上面可以看出,前者的内核比后者的内核长。后者的内核执行时间太短,导致 GPU 利用率较低。
估计 SM 效率:每个内核的估计 SM 效率在 0-100% 之间。例如,下面的内核只有 64 个块,而此 GPU 中的 SM 为 80。那么它的“估计 SM 效率”是 64/80,即 0.8。

云存储支持
安装 pip install tensorboard 后,若要通过这些云提供商读取数据,您现在可以运行:
torch-tb-profiler[blob]
torch-tb-profiler[gs]
torch-tb-profiler[s3]
pip install torch-tb-profiler[blob]
、pip install torch-tb-profiler[gs]
或 pip install torch-tb-profiler[S3]
以通过这些云提供商读取数据。欲了解更多信息,请参阅此README。
跳转到源代码:
TensorBoard 和 PyTorch Profiler 直接集成到 Visual Studio Code (VS Code) 的一个巨大好处是能够直接从分析器堆栈跟踪跳转到源代码(文件和行)。VS Code Python 扩展现在支持 TensorBoard 集成。
“跳转到源”功能仅在 Tensorboard 在 VS Code 中启动时可用。如果在分析时 with_stack=True,则堆栈跟踪将显示在插件 UI 上。当您单击 PyTorch Profiler 中的堆栈跟踪时,VS Code 将自动并排打开相应文件,并直接跳转到您感兴趣的代码行,以便您进行调试。这使您能够根据分析结果和建议快速对代码进行可操作的优化和更改。
Gify:使用 Visual Studio Code 插件 UI 跳转到源代码
有关如何优化批处理大小性能的详细教程,请参阅此处。PyTorch Profiler 也已与 PyTorch Lightning 集成,您可以简单地使用 --trainer.profiler=pytorch
标志启动 Lightning 训练作业以生成跟踪。
PyTorch Profiler 的下一步是什么?
您刚刚看到了 PyTorch Profiler 如何帮助优化模型。现在您可以尝试通过 pip install torch-tb-profiler
来优化您的 PyTorch 模型。
请期待未来更高级的本教程版本。我们也很高兴继续为 PyTorch 用户带来最先进的工具,以提高 ML 性能。我们很乐意听取您的意见。请随时在此处提出问题。
有关 PyTorch Profiler 即将推出的新颖和令人兴奋的功能,请在 Twitter 上关注 @PyTorch,并在 pytorch.org 上查看我们。
致谢
作者在此感谢以下个人为此文所做的贡献。Facebook 方面:Geeta Chauhan、Gisle Dankel、Woo Kim、Sam Farahzad 和 Mark Saroufim。Microsoft 方面:AI 框架工程师(Teng Gao、Mike Guo 和 Yang Gu)、Guoliang Hua 和 Thuy Nguyen。