深度学习训练与推理的性能分析(Profiling)

在深度学习的工程实践中,性能瓶颈往往不是一眼就能看出来的。无论是训练还是推理阶段,都需要借助 profiling 工具来定量分析各个环节的耗时,才能有针对性地做优化。这篇笔记记录了我在训练和推理两个阶段分别用到的 profiling 方法。

训练过程的 Profiling

训练阶段的 profiling 主要目的是分析数据加载、前向传播、反向传播各部分的时间占用,找出整个训练流程里的时间瓶颈。

在 PyTorch 中,我用的是 NVTX(NVIDIA Tools Extension)来做标注。在训练循环里,针对每个主要阶段(数据加载、前向、loss 计算、反向、optimizer 更新)前后插入标记,代码写成如下这样:

import torch.cuda.nvtx as nvtx

def train(args, model, device, train_loader, optimizer, epoch):
    model.train()
    for batch_idx, (data, target) in enumerate(train_loader):
        nvtx.range_push("Batch " + str(batch_idx))

        nvtx.range_push("Copy to device")
        data, target = data.to(device), target.to(device)
        nvtx.range_pop()

        nvtx.range_push("Forward pass")
        optimizer.zero_grad()
        output = model(data)
        loss = F.nll_loss(output, target)
        nvtx.range_pop()
        nvtx.range_pop()

经过标注之后,用 Nsight Systems 打开采集结果,时间线会按 NVTX 区间着色,各阶段耗时一目了然。自己测试了一下,实际效果如下图所示,确实挺有用的,再也不用靠打印时间戳来做粗粒度估计了:

Nsight Systems 时间线按 NVTX 区间着色,各训练阶段耗时清晰可见
图 1:Nsight Systems 中按 NVTX 区间着色的训练时间线

推理过程的 Profiling

推理阶段的情况稍有不同。通常的做法是先把 PyTorch 训练好的模型转换为 TensorRT,再用 TensorRT 进行推理部署。针对这个流程的 profiling,需要在 TensorRT 的上下文中进行,与训练阶段的 NVTX 标注方式有所区别,后续打算进一步整理这部分的具体用法。