本文翻译自:https://pytorch.org/tutorials/recipes/recipes/tuning_guide.html#general-optimizationspytorch.org/tutorials/recipes/recipes/tuning_guide.html#general-optimizations
性能调优指南是一组优化和最佳实践,可以加速 PyTorch 中深度学习模型的训练和推理。所提出的技术通常可以通过仅更改几行代码来实现,并且可以应用于所有领域的广泛深度学习模型。
启用异步数据加载和扩充
torch.utils.data.DataLoader 支持在单独的工作子进程中进行异步数据加载和数据扩充。默认设置为DataLoader,num_workers=0表示数据加载是同步的,在主进程中完成。因此,主训练过程必须等待数据可用才能继续执行。
设置启用异步数据加载以及训练和数据加载之间的重叠。应根据工作负载、CPU、GPU 和训练数据的位置进行调整。
num_workers > 0num_workers
DataLoader接受pin_memory参数,默认为False. 使用 GPU 时最好设置
pin_memory=True,这指示 DataLoader使用固定内存并启用从主机到 GPU 的更快和异步内存复制。
禁用梯度计算以进行验证或推理
PyTorch 从所有涉及需要梯度的张量的操作中保存中间缓冲区。通常,验证或推理不需要梯度。torch.no_grad()上下文管理器可用于禁用指定代码块内的梯度计算,这可以加快执行速度并减少所需的内存量。
torch.no_grad()也可以用作函数装饰器。
禁用卷积的偏差,直接跟随批处理规范
torch.nn.Conv2d() 具有bias默认为的参数True(对于 Conv1d 和 Conv3d也是如此 )。
如果一个nn.Conv2d层后面直接跟一个nn.BatchNorm2d层,那么卷积中的偏差就不需要了,而是使用 . 不需要偏差,因为在第一步中减去了平均值,这有效地抵消了偏差的影响。nn.Conv2d(…, bias=False, …)BatchNorm
这也适用于 1d 和 3d 卷积,只要BatchNorm(或其他归一化层)在与卷积偏差相同的维度上归一化。
torchvision提供的模型 已经实现了这种优化。
使用 parameter.grad = None 代替 model.zero_grad() 或 optimizer.zero_grad()
而不是调用:
model.zero_grad()
#or
optimizer.zero_grad()
要将梯度归零,请改用以下方法:
for param in model.parameters():
param.grad = None
第二个代码片段不会将每个单独参数的内存归零,随后的反向传递也使用赋值而不是加法来存储梯度,这减少了内存操作的数量。
将梯度设置为None与将其设置为零的数值行为略有不同,有关更多详细信息,请参阅 文档。
或者,从 PyTorch 1.7 开始,调用model或 optimizer.zero_grad(set_to_none=True).
融合逐点操作
逐点运算(逐元素加法、乘法、数学函数 - sin()、cos()等sigmoid())可以融合到单个内核中,以摊销内存访问时间和内核启动时间。
PyTorch JIT可以自动融合内核,尽管编译器中可能还没有实现其他融合机会,并且并非所有设备类型都受到同等支持。
逐点操作是受内存限制的,对于每个操作 PyTorch 都会启动一个单独的内核。每个内核从内存中加载数据,执行计算(这一步通常很便宜)并将结果存储回内存中。
Fused operator 只为多个 fused pointwise ops 启动一个内核,并且只将数据加载/存储一次到内存中。这使得 JIT 对于激活函数、优化器、自定义 RNN 单元等非常有用。
在最简单的情况下,可以通过将 torch.jit.script 装饰器应用于函数定义来启用融合,例如:
@torch.jit.scriptdef fused_gelu(x): return x * 0.5 * (1.0 + torch.erf(x / 1.41421))
为计算机视觉模型启用 channels_last 内存格式PyTorch 1.5 引入了channels_last对卷积网络内存格式的支持。此格式旨在与 AMP结合使用,以进一步加速具有 Tensor Cores的卷积神经网络。
支持channels_last是实验性的,但预计适用于标准计算机视觉模型(例如 ResNet-50、SSD)。要将模型转换为 channels_last格式,请遵循 Channels Last Memory Format Tutorial。本教程包括有关 转换现有模型的部分。
检查点中间缓冲区
缓冲区检查点是一种减轻模型训练的内存容量负担的技术。它不是存储所有层的输入来计算反向传播中的上游梯度,而是存储几个层的输入,而其他层在反向传播期间重新计算。减少的内存需求可以增加批量大小,从而提高利用率。
应仔细选择检查点目标。最好不要存储重计算成本小的大层输出。示例目标层是激活函数(例如ReLU、Sigmoid、Tanh)、上/下采样和具有小累积深度的矩阵向量操作。
PyTorch 支持原生的
torch.utils.checkpoint API 来自动执行检查点和重新计算。
禁用调试 API
许多 PyTorch API 用于调试,应在常规训练运行时禁用:
异常检测:
torch.autograd.detect_anomaly 或 torch.autograd.set_detect_anomaly(True)
探查器相关:
torch.autograd.profiler.emit_nvtx, torch.autograd.profiler.profileautograd gradcheck: torch.autograd.gradcheck 或 torch.autograd.gradgradcheck