使用 Instrumentation and Tracing Technology (ITT) API 分析 PyTorch 工作负载¶
在本食谱中,您将学习
什么是 Intel® VTune™ 分析器
什么是 Instrumentation and Tracing Technology (ITT) API
如何在 Intel® VTune™ 分析器中可视化 PyTorch 模型层次结构
一个简短的示例代码,展示如何使用 PyTorch ITT API
什么是 Intel® VTune™ 分析器¶
Intel® VTune™ 分析器是一种用于串行和多线程应用程序的性能分析工具。对于熟悉 Intel 架构的用户,Intel® VTune™ 分析器提供了一套丰富的指标,帮助用户了解应用程序如何在 Intel 平台上执行,从而了解性能瓶颈在哪里。
更多详细信息,包括入门指南,可在 英特尔网站 上找到。
什么是 Instrumentation and Tracing Technology (ITT) API¶
Intel® VTune™ 分析器提供的 Instrumentation and Tracing Technology API (ITT API) 使目标应用程序能够在执行期间生成和控制跟踪数据的收集。
ITT 功能的优势在于可以在 Intel® VTune™ 分析器 GUI 上标记各个 PyTorch 运算符以及自定义区域的时间跨度。当用户发现任何异常情况时,定位哪个运算符的行为异常将非常有帮助。
注意
ITT API 自 PyTorch 1.13 版本起已集成到 PyTorch 中。用户无需调用原始的 ITT C/C++ API,只需调用 PyTorch 中的 Python API 即可。更多详细信息请参见 PyTorch 文档。
如何在 Intel® VTune™ Profiler 中可视化 PyTorch 模型层次结构¶
PyTorch 提供了两种使用方式
隐式调用:默认情况下,所有遵循 PyTorch 算子注册机制注册的算子,在其功能启用时都会由 ITT 功能自动标记。
显式调用:如果需要自定义标记,用户可以使用 PyTorch 文档 中提到的 API 显式地标记所需范围。
要启用显式调用,需要在 torch.autograd.profiler.emit_itt() 范围内调用需要标记的代码。例如
with torch.autograd.profiler.emit_itt():
<code-to-be-profiled...>
启动 Intel® VTune™ Profiler¶
要验证功能,您需要启动一个 Intel® VTune™ Profiler 实例。请查看 Intel® VTune™ Profiler 用户指南 以了解启动 Intel® VTune™ Profiler 的步骤。
启动 Intel® VTune™ Profiler GUI 后,您应该会看到如下用户界面
左侧导航栏的 sample (matrix) 项目下提供了三个示例结果。如果您不希望性能分析结果出现在此默认示例项目中,可以通过蓝色 Configure Analysis… 按钮下的 New Project… 按钮创建一个新项目。要开始新的性能分析,请单击蓝色 Configure Analysis… 按钮以启动性能分析配置。
配置性能分析¶
单击 Configure Analysis… 按钮后,您应该会看到如下屏幕
窗口的右侧分为三部分:WHERE(左上)、WHAT(左下)和 HOW(右)。使用 WHERE,您可以指定要在其上运行性能分析的机器。使用 WHAT,您可以设置要分析的应用程序的路径。要分析 PyTorch 脚本,建议将所有手动步骤(包括激活 Python 环境和设置所需的环境变量)包装到一个 bash 脚本中,然后分析此 bash 脚本。在上图中,我们将所有步骤包装到 launch.sh bash 脚本中,并使用参数 <path_of_launch.sh> 分析 bash。在右侧 HOW 中,您可以选择您希望分析的任何类型。Intel® VTune™ Profiler 提供了许多您可以选择的性能分析类型。详细信息请参见 Intel® VTune™ Profiler 用户指南。
读取性能分析结果¶
使用 ITT 成功进行性能分析后,您可以打开性能分析结果的 Platform 选项卡以在 Intel® VTune™ Profiler 时间轴上查看标签。
时间轴将主线程显示为顶部的 python 线程,下方显示各个 OpenMP 线程。标记的 PyTorch 算子和自定义区域显示在主线程行中。所有以 aten:: 开头的算子都是 PyTorch 中由 ITT 功能隐式标记的算子。标签 iteration_N 是使用特定的 API torch.profiler.itt.range_push()、torch.profiler.itt.range_pop() 或 torch.profiler.itt.range() 范围显式标记的。有关详细信息,请查看下一节中的示例代码。
注意
标记有 convolution 和 reorder 的红色框来自 Intel® oneAPI 深度神经网络库 (oneDNN)。
如右侧导航栏所示,时间轴行中的棕色部分显示各个线程的 CPU 使用率。在某个时间戳处,线程行中棕色部分所占高度的百分比与该线程在该时间戳处的 CPU 使用率百分比一致。因此,从该时间轴可以直观地了解以下内容
每个线程上 CPU 内核的利用率如何。
所有线程上 CPU 内核的利用率是否均衡。所有线程的 CPU 使用率是否良好?
OpenMP 线程的同步情况如何。启动 OpenMP 线程或 OpenMP 线程完成时是否存在抖动。
当然,Intel® VTune™ Profiler 提供了更多丰富的性能分析功能来帮助您理解性能问题。当您理解性能问题的根本原因后,就可以解决它。更多详细的使用说明请参见 Intel® VTune™ Profiler 用户指南。
展示如何使用 PyTorch ITT API 的简短示例代码¶
以下示例代码是在上图截图中用于性能分析的脚本。
拓扑结构由两个算子 Conv2d 和 Linear 组成。执行了三次推理迭代。每次迭代都由 PyTorch ITT API 标记为文本字符串 iteration_N。 torch.profile.itt.range_push 和 torch.profile.itt.range_pop 或 torch.profile.itt.range 范围的任意一对都实现了自定义标记功能。
# sample.py
import torch
import torch.nn as nn
class ITTSample(nn.Module):
def __init__(self):
super(ITTSample, self).__init__()
self.conv = nn.Conv2d(3, 5, 3)
self.linear = nn.Linear(292820, 1000)
def forward(self, x):
x = self.conv(x)
x = x.view(x.shape[0], -1)
x = self.linear(x)
return x
def main():
m = ITTSample()
x = torch.rand(10, 3, 244, 244)
with torch.autograd.profiler.emit_itt():
for i in range(3)
# Labeling a region with pair of range_push and range_pop
#torch.profiler.itt.range_push(f'iteration_{i}')
#m(x)
#torch.profiler.itt.range_pop()
# Labeling a region with range scope
with torch.profiler.itt.range(f'iteration_{i}'):
m(x)
if __name__ == '__main__':
main()
在 Intel® VTune™ Profiler GUI 截图中提到的用于包装所有手动步骤的 launch.sh bash 脚本如下所示。
# launch.sh
#!/bin/bash
# Retrieve the directory path where the path contains both the sample.py and launch.sh so that this bash script can be invoked from any directory
BASEFOLDER=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
<Activate a Python environment>
cd ${BASEFOLDER}
python sample.py