1 考虑换一种学习率
    学习率 schedule 的选择对模型的收敛速度和泛化能力有很大的影响,Leslie N. Smith 等人在论文《Cyclical Learning Rates for Training Neural Networks》、《Super-Convergence: Very Fast Training of Neural Networks Using Large Learning Rates 》中提出了周期性(Cyclical)学习率以及 1Cycle 学习率 schedule。与传统的学习率 schedule 相比,在最好的情况下,该 schedule 实现了巨大的加速(Smith 称之为超级收敛)。之后,fast.ai 的 Jeremy Howard 和 Sylvain Gugger 对其进行了推广。Pytorch 已经实现了这两种方法:「torch.optim.lr_scheduler.CyclicLR」和「torch.optim.lr_scheduler.OneCycleLR」
    2 在 DataLoader 中使用多个 worker 和页锁定内存
    当使用 torch.utils.data.DataLoader 时,设置 num_workers > 0,而不是默认值 0,同时设置 pin_memory=True,而不是默认值 False。来自 NVIDIA 的高级 CUDA 深度学习算法软件工程师 Szymon Micacz 就曾使用四个 worker 和页锁定内存(pinned memory)在单个 epoch 中实现了 2 倍的加速。人们选择 worker 数量的经验法则是将其设置为可用 GPU 数量的四倍,大于或小于这个数都会降低训练速度。请注意,增加 num_workers 将增加 CPU 内存消耗。
    3. 把 batch 调到最大
    把 batch 调到最大是一个颇有争议的观点。一般来说,如果在 GPU 内存允许的范围内将 batch 调到最大,你的训练速度会更快。但是,你也必须调整其他超参数,比如学习率。一个比较好用的经验是,batch 大小加倍时,学习率也要加倍。
    4. 使用自动混合精度(AMP)
    PyTorch 1.6 版本包括对 PyTorch 的自动混合精度训练的本地实现。与单精度 (FP32) 相比,某些运算在半精度 (FP16) 下运行更快,而不会损失准确率。AMP 会自动决定应该以哪种精度执行哪种运算。这样既可以加快训练速度,又可以减少内存占用。
    5. 考虑使用另一种优化器
    6. cudNN 基准
    如果你的模型架构保持不变、输入大小保持不变,设置 torch.backends.cudnn.benchmark = True
    7. 小心 CPU 和 GPU 之间频繁的数据传输
    8. 使用梯度 / 激活 checkpointing
    Checkpointing 的工作原理是用计算换内存,并不存储整个计算图的所有中间激活用于 backward pass,而是重新计算这些激活。我们可以将其应用于模型的任何部分。
    9. 使用梯度积累
    增加 batch 大小的另一种方法是在调用 optimizer.step() 之前在多个. backward() 传递中累积梯度
    10. 使用分布式数据并行进行多 GPU 训练
    加速分布式训练可能有很多方法,但是简单的方法是使用 torch.nn.DistributedDataParallel 而不是 torch.nn.DataParallel。这样一来,每个 GPU 将由一个专用的 CPU 核心驱动,避免了 DataParallel 的 GIL 问题
    11. 设置梯度为 None 而不是 0
    梯度设置为. zero_grad(set_to_none=True) 而不是 .zero_grad()。这样做可以让内存分配器处理梯度,而不是将它们设置为 0。
    12. 使用. as_tensor() 而不是. tensor()
    torch.tensor() 总是会复制数据。如果你要转换一个 numpy 数组,使用 torch.as_tensor() 或 torch.from_numpy() 来避免复制数据。
    13. 必要时打开调试工具
    请确保当你需要调试时再打开调试器,不需要时要及时关掉,因为调试器会降低你的训练速度。
    14. 使用梯度裁剪
    关于避免 RNN 中的梯度爆炸的问题,已经有一些实验和理论证实,梯度裁剪(gradient = min(gradient, threshold))可以加速收敛。
    15. 在 BatchNorm 之前关闭 bias
    16. 在验证期间关闭梯度计算
    17. 使用输入和 batch 归一化
    要再三检查一下输入是否归一化?是否使用了 batch 归一化?
    **