注意
单击此处下载完整的示例代码
带有 TensorBoard 的 PyTorch Profiler¶
创建时间: 2021 年 4 月 20 日 |上次更新时间:2024 年 10 月 31 日 |上次验证: Nov 05, 2024
本教程演示如何将 TensorBoard 插件与 PyTorch Profiler 结合使用 来检测模型的性能瓶颈。
警告
TensorBoard 与 PyTorch 分析器的集成现已推出
荒废的。相反,请使用 Perfetto 或 Chrome 跟踪来
查看文件。生成跟踪后,
只需将 拖动到 Perfetto UI 中或可视化您的配置文件。trace.json
trace.json
chrome://tracing
介绍¶
PyTorch 1.8 包括一个更新的分析器 API,该 API 能够 记录 CPU 端操作以及 GPU 端的 CUDA 内核启动。 分析器可以可视化此信息 在 TensorBoard Plugin 中提供性能瓶颈分析。
在本教程中,我们将使用一个简单的 Resnet 模型来演示如何 使用 TensorBoard 插件分析模型性能。
步骤¶
准备数据和模型
使用 Profiler 记录执行事件
运行 Profiler
使用 TensorBoard 查看结果并分析模型性能
在 Profiler 的帮助下提高性能
使用其他高级功能分析性能
其他做法:在 AMD GPU 上分析 PyTorch
1. 准备数据和模型¶
首先,导入所有必要的库:
import torch
import torch.nn
import torch.optim
import torch.profiler
import torch.utils.data
import torchvision.datasets
import torchvision.models
import torchvision.transforms as T
然后准备输入数据。在本教程中,我们使用 CIFAR10 数据集。
将其转换为所需的格式并用于加载每个批次。DataLoader
transform = T.Compose(
[T.Resize(224),
T.ToTensor(),
T.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
train_set = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
train_loader = torch.utils.data.DataLoader(train_set, batch_size=32, shuffle=True)
接下来,创建 Resnet 模型、损失函数和优化器对象。 要在 GPU 上运行,请将 model 和 loss 移动到 GPU 设备。
device = torch.device("cuda:0")
model = torchvision.models.resnet18(weights='IMAGENET1K_V1').cuda(device)
criterion = torch.nn.CrossEntropyLoss().cuda(device)
optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
model.train()
定义每批输入数据的训练步骤。
def train(data):
inputs, labels = data[0].to(device=device), data[1].to(device=device)
outputs = model(inputs)
loss = criterion(outputs, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
2. 使用 Profiler 记录执行事件¶
Profiler 通过上下文管理器启用,并接受多个参数 一些最有用的是:
schedule
- 将 step (int) 作为单个参数的 callable 并返回要在每个步骤中执行的 Profiler 操作。在此示例中,使用 , Profiler 将跳过第一步/迭代, 从第二个开始热身, 记录以下 3 次迭代, 之后,跟踪将变为可用,并调用 on_trace_ready(如果已设置)。 该循环总共重复一次。每个循环在 TensorBoard 插件中称为 “span”。
wait=1, warmup=1, active=3, repeat=1
在步骤中,Profiler 处于禁用状态。 在步骤中,分析器开始跟踪,但结果将被丢弃。 这是为了减少性能分析开销。 性能分析开始时的开销很高,很容易给性能分析结果带来偏差。 在步骤中,Profiler 会工作并记录事件。
wait
warmup
active
on_trace_ready
- 在每个周期结束时调用的 callable; 在此示例中,我们使用为 TensorBoard 生成结果文件。 分析后,结果文件将保存到目录中。 指定此目录作为参数,用于分析 TensorBoard 中的配置文件。torch.profiler.tensorboard_trace_handler
./log/resnet18
logdir
record_shapes
- 是否记录运算符输入的形状。profile_memory
- 跟踪张量内存分配/释放。注意,对于旧版本的 pytorch 版本为 在 1.10 之前,如果您遇到较长的分析时间,请禁用它或升级到新版本。with_stack
- 记录操作的源信息(文件和行号)。 如果 TensorBoard 是在 VS Code 中启动的(参考), 单击堆栈帧将导航到特定的代码行。
with torch.profiler.profile(
schedule=torch.profiler.schedule(wait=1, warmup=1, active=3, repeat=1),
on_trace_ready=torch.profiler.tensorboard_trace_handler('./log/resnet18'),
record_shapes=True,
profile_memory=True,
with_stack=True
) as prof:
for step, batch_data in enumerate(train_loader):
prof.step() # Need to call this at each step to notify profiler of steps' boundary.
if step >= 1 + 1 + 3:
break
train(batch_data)
或者,也支持以下非上下文管理器 start/stop。
prof = torch.profiler.profile(
schedule=torch.profiler.schedule(wait=1, warmup=1, active=3, repeat=1),
on_trace_ready=torch.profiler.tensorboard_trace_handler('./log/resnet18'),
record_shapes=True,
with_stack=True)
prof.start()
for step, batch_data in enumerate(train_loader):
prof.step()
if step >= 1 + 1 + 3:
break
train(batch_data)
prof.stop()
3. 运行 Profiler¶
运行上述代码。性能分析结果将保存在 directory../log/resnet18
4. 使用 TensorBoard 查看结果并分析模型性能¶
注意
TensorBoard 插件支持已弃用,因此其中一些函数可能不会 像以前一样工作。请看一下替代品 HTA。
安装 PyTorch Profiler TensorBoard 插件。
pip install torch_tb_profiler
启动 TensorBoard。
tensorboard --logdir=./log
在 Google Chrome 浏览器或 Microsoft Edge 浏览器(不支持 Safari)中打开 TensorBoard 配置文件 URL。
http://localhost:6006/#pytorch_profiler
您可以看到 Profiler 插件页面,如下所示。
概述
概述显示了模型性能的高级摘要。
“GPU 摘要”面板显示 GPU 配置、GPU 使用情况和 Tensor Core 使用情况。 在此示例中,GPU 利用率较低。 这些指标的详细信息在这里。
“Step Time Breakdown” 显示不同执行类别中每个步骤所花费的时间分布。
在此示例中,您可以看到开销很大。DataLoader
底部的 “Performance Recommendation” 使用分析数据 自动突出显示可能的瓶颈, 并为您提供可操作的优化建议。
您可以在左侧的 “Views” 下拉列表中更改视图页面。
操作员视图
操作员视图显示每个 PyTorch 操作员的性能 ,该操作将在主机或设备上执行。
“Self” 持续时间不包括其子运算符的时间。 “Total” 持续时间包括其子运算符的时间。
查看调用堆栈
点击运算符的 ,将显示名称相同但调用堆栈不同的运算符。
然后点击该子表中的 a,将显示调用堆栈帧。View Callstack
View Callstack
如果 TensorBoard 在 VS Code 中启动 (启动指南)、 单击调用堆栈帧将导航到特定的代码行。
内核视图
GPU 内核视图显示所有内核在 GPU 上花费的时间。
使用的 Tensor 核心: 此内核是否使用 Tensor Core。
每 SM 的平均区间数: 每个 SM 的块数 = 此内核的块数 / 此 GPU 的 SM 编号。 如果此数字小于 1,则表示 GPU 多处理器未得到充分利用。 “Mean Blocks per SM” 是使用此内核名称的所有运行的加权平均值,使用每次运行的持续时间作为权重。
平均估计入住率: Est. Achieved Occupancy 在此列的工具提示中定义。 对于大多数情况,例如内存带宽有限内核,越高越好。 “Mean Est. Achieved Occupancy” 是该内核名称的所有运行的加权平均值, 使用每次运行的持续时间作为权重。
跟踪视图
trace (跟踪) 视图显示分析的运算符和 GPU 内核的时间线。 您可以选择它以查看详细信息,如下所示。
您可以借助右侧工具栏移动图表并放大/缩小。 键盘还可用于在时间轴内缩放和移动。 'w' 和 's' 键以鼠标为中心进行放大, “A”和“D”键可左右移动时间轴。 您可以多次点击这些键,直到看到可读的表示形式。
如果 backward 运算符的 “Incoming Flow” 字段的值为 “forward correspond to backward”, 您可以单击文本以获取其 Launching forward 运算符。
在此示例中,我们可以看到前缀为 的事件花费了大量时间。
在此期间的大部分时间里,GPU 都是空闲的。
因为这个函数是在主机端加载数据和转换数据,
在此期间,GPU 资源被浪费。enumerate(DataLoader)
5. 借助 Profiler 提高性能¶
在“Overview(概述)”页面的底部,“Performance Recommendation(性能建议)”中的建议暗示瓶颈是 。
默认情况下,PyTorch 使用单个进程。
用户可以通过设置参数 来启用多进程数据加载。以下是更多详细信息。DataLoader
DataLoader
num_workers
在此示例中,我们遵循 “Performance Recommendation” 并设置如下:
传递一个不同的名称,例如 to ,然后再次运行它。num_workers
./log/resnet18_4workers
tensorboard_trace_handler
train_loader = torch.utils.data.DataLoader(train_set, batch_size=32, shuffle=True, num_workers=4)
然后,让我们在左侧的 “Runs” 下拉列表中选择最近分析的运行。
从上面的视图可以看出,与上一次运行的 132ms 相比,单步时间减少了大约 76ms,
以及主要贡献的时间减少。DataLoader
从上面的视图可以看出,的运行时间减少了,
GPU 利用率提高。enumerate(DataLoader)
6. 使用其他高级功能分析性能¶
内存视图
要分析内存,必须在 的参数中设置为 。profile_memory
True
torch.profiler.profile
您可以使用 Azure 上的现有示例进行试用
pip install azure-storage-blob
tensorboard --logdir=https://torchtbprofiler.blob.core.windows.net/torchtbprofiler/demo/memory_demo_1_10
分析器在性能分析期间记录所有内存分配/释放事件和分配器的内部状态。 内存视图由三个组件组成,如下所示。
这些组件分别是 Memory Curve Graph、Memory Events Table 和 Memory Statistics Table,从上到下。
可以在 “Device” 选择框中选择内存类型。 例如,“GPU0” 表示下表仅显示每个运算符在 GPU 0 上的内存使用情况,不包括 CPU 或其他 GPU。
内存曲线显示内存消耗的趋势。“已分配” 曲线显示实际 正在使用,例如 Tensors。在 PyTorch 中,CUDA 分配器和其他一些分配器中使用了缓存机制。这 “Reserved” 曲线显示分配器保留的总内存。您可以在图表上单击鼠标左键并拖动 要在所需范围内选择事件:
选择后,这三个组件将在限制的时间范围内进行更新,以便您获得更多 信息。通过重复此过程,您可以放大到非常精细的细节。右键单击图表 会将图表重置为初始状态。
在 memory events 表中,allocation 和 release 事件成对到一个条目中。“operator” 列显示
导致分配的直接 ATen 运算符。请注意,在 PyTorch 中,ATen 运算符通常用于分配内存。例如,按照后跟 .仅显示操作员名称,因为帮助不大。它将如此特殊情况所示。“分配时间”、“释放时间”和“持续时间”
如果事件发生在时间范围之外,则可能会缺少列的数据。aten::empty
aten::ones
aten::empty
aten::fill_
aten::empty
aten::ones (aten::empty)
在内存统计信息表中,“Size Increase” 列将所有分配大小相加,并减去所有内存 release size,即该算子之后内存使用量的净增加量。“自身大小增加”列为 类似于 “Size Increase”,但它不计算子运算符的分配。关于 ATen 运维的 implementation detail,则某些运算符可能会调用其他运算符,因此内存分配可以发生在 call 堆栈。也就是说,“Self Size Increase” 仅计算当前调用堆栈级别的内存使用量增加。 最后,“Allocation Size” 列汇总了所有分配,而不考虑内存释放。
分布式视图
该插件现在支持以 NCCL/GLOO 作为后端分析 DDP 的分布式视图。
可以使用 Azure 上的现有示例进行尝试:
pip install azure-storage-blob
tensorboard --logdir=https://torchtbprofiler.blob.core.windows.net/torchtbprofiler/demo/distributed_bert
“计算/通信概述”显示了计算/通信比率及其重叠程度。 从这个视图中,用户可以找出 worker 之间的负载均衡问题。 例如,如果一个 worker 的计算 + 重叠时间比其他 worker 大得多, 可能存在负载均衡问题,或者此 worker 可能是落后者。
“同步/通信概述”显示了通信的效率。 “数据传输时间”是指实际交换数据的时间。 “同步时间” 是等待并与其他 worker 同步的时间。
如果一个 worker 的 “同步时间” 比其他 worker 的 “同步时间” 短得多, 这个 worker 可能是一个落后者,可能比其他 worker 有更多的计算工作负载。
“Communication Operations Stats” 汇总了每个 worker 中所有 communication operations 的详细统计数据。
7. 其他实践:在 AMD GPU 上分析 PyTorch¶
AMD ROCm 平台是专为 GPU 计算而设计的开源软件堆栈,由驱动程序、开发工具和 API 组成。 我们可以在 AMD GPU 上运行上述步骤。在本节中,我们将使用 Docker 安装 ROCm 基础开发映像 在安装 PyTorch 之前。
例如,让我们创建一个名为 的目录,并将步骤 1 中的代码保存为此目录中的代码。profiler_tutorial
test_cifar10.py
mkdir ~/profiler_tutorial
cd profiler_tutorial
vi test_cifar10.py
在撰写本文时,ROCm 平台上的 PyTorch 的 Stable() Linux 版本是 ROCm 5.6。2.1.1
从 Docker Hub 获取具有正确用户空间 ROCm 版本的基础 Docker 映像。
是的。rocm/dev-ubuntu-20.04:5.6
启动 ROCm 基础 Docker 容器:
docker run -it --network=host --device=/dev/kfd --device=/dev/dri --group-add=video --ipc=host --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --shm-size 8G -v ~/profiler_tutorial:/profiler_tutorial rocm/dev-ubuntu-20.04:5.6
在容器内,安装安装 wheels 包所需的任何依赖项。
sudo apt update
sudo apt install libjpeg-dev python3-dev -y
pip3 install wheel setuptools
sudo apt install python-is-python3
安装轮子:
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/rocm5.6
安装 ,然后运行 Python 文件 :
torch_tb_profiler
test_cifar10.py
pip install torch_tb_profiler
cd /profiler_tutorial
python test_cifar10.py
现在,我们有了在 TensorBoard 中查看所需的所有数据:
tensorboard --logdir=./log
选择不同的视图,如步骤 4 中所述。例如,下面是 Operator 视图:
在编写此部分时,Trace (跟踪) 视图不起作用,并且不显示任何内容。您可以通过在 Chrome 浏览器中输入来解决此问题。chrome://tracing
将目录下的文件复制到 Windows。
trace.json
~/profiler_tutorial/log/resnet18
如果文件位于远程位置,则可能需要使用 复制文件。scp
单击 Load (加载) 按钮,从浏览器中的页面加载跟踪 JSON 文件。
chrome://tracing
如前所述,您可以移动图形并放大和缩小。
您还可以使用键盘在时间轴内缩放和移动。
和 键以鼠标为中心进行放大,
和 和 键可左右移动时间轴。
您可以多次点击这些键,直到看到可读的表示形式。w
s
a
d