在深度学习开发里,训练慢通常不是单一原因:有时是数据喂得太慢,有时是显存被浪费了,也有时只是把硬件用得不够满。下面这 9 个方法,基本都围绕 PyTorch 和 PyTorch-Lightning 的常见做法展开,偏实战,不追求花哨,但对大多数项目都能直接见效。
PyTorch-Lightning 只是把训练流程包了一层,核心还是 PyTorch。本身不会替你把模型变快,但它把很多参数和训练策略收拢得更清楚,适合拿来说明这些优化点。
1. 先把数据加载做好
训练速度卡住,最常见的地方其实不是 GPU,而是数据读取。比起把数据整成 h5py 或 numpy 再在主进程里慢慢读,直接用 DataLoader 往往更省事,也更容易把吞吐拉起来。图像任务可以直接上 PyTorch 的数据集和 DataLoader,NLP 场景则可以看看 TorchText。
在 PyTorch-Lightning 里,数据管道配置好之后,训练循环就不用自己一层层写了,框架会按你提供的 DataLoader 去跑。
from torch.utils.data import DataLoader
from torchvision.datasets import MNIST
dataset = MNIST(root='./data', train=True, download=True)
loader = DataLoader(dataset, batch_size=32, shuffle=True, num_workers=4, pin_memory=True)
for batch in loader:
x, y = batch
model.training_step(x, y)
这里 shuffle=True 是为了打乱样本顺序,pin_memory=True 则能让 CPU 到 GPU 的拷贝更顺一点。这个参数经常被忽略,但在 GPU 训练里挺实用。
2. 把 num_workers 调起来
DataLoader 默认是主进程读数据,数据集一大,IO 就会拖后腿。num_workers 的作用就是把加载工作拆到多个进程里,减少等待时间。
# 慢:主进程加载
loader = DataLoader(dataset, batch_size=32, shuffle=True)
# 快:启用 4 个 worker 进程
loader = DataLoader(dataset, batch_size=32, shuffle=True, num_workers=4)
一般可以从 4 或 8 开始试,接近 CPU 核心数不一定最优,但比完全不开强很多。别一上来就拉满,worker 太多会和别的任务抢内存、抢磁盘,最后反而抖得更厉害。
3. 批量大小尽量用满显存
batch size 往大调,通常是最直接的提速手段。更大的 batch 能让 GPU 更连续地干活,减少一次次小批次切换带来的浪费。很多时候,模型不是算不过来,而是算得太碎。
不过这一步有明显代价:显存会上去,学习率也往往要跟着改。常见做法是按线性缩放思路去调学习率,但具体还是得结合模型和数据看,不是机械套公式就行。

