Ubuntu系统下PyTorch内存不足的解决方法
批量大小是影响GPU显存占用的核心因素之一。减小DataLoader中的batch_size(如从64降至32或16),可直接降低单次前向/反向传播的内存需求。需注意:过小的批量可能导致训练不稳定或收敛速度变慢,需通过实验找到平衡点。
若无法进一步减小批量大小,可通过梯度累积模拟大批次训练。具体做法:在多个小批量上累积梯度(不立即更新模型参数),待累积到指定步数后再执行一次参数更新。示例代码:
optimizer.zero_grad()
for i, (data, label) in enumerate(dataloader):
output = model(data)
loss = criterion(output, label)
loss.backward() # 累积梯度
if (i+1) % accumulation_steps == 0: # 累积指定步数后更新参数
optimizer.step()
optimizer.zero_grad()
此方法可保持内存占用不变的同时,提升训练效果。
PyTorch会缓存计算结果以加速后续操作,但未使用的缓存会占用显存。可通过以下方式手动释放:
del variable_name;torch.cuda.empty_cache()清理未使用的缓存。混合精度结合float16(半精度)和float32(单精度)计算,在保持模型精度的前提下,减少显存占用并加速训练。使用PyTorch的torch.cuda.amp模块实现自动混合精度:
scaler = torch.cuda.amp.GradScaler() # 梯度缩放器(防止数值溢出)
for data, label in dataloader:
optimizer.zero_grad()
with torch.cuda.amp.autocast(): # 自动选择float16/float32
output = model(data)
loss = criterion(output, label)
scaler.scale(loss).backward() # 缩放梯度以避免溢出
scaler.step(optimizer) # 更新参数
scaler.update() # 调整缩放因子
需确保GPU支持Tensor Cores(如NVIDIA Volta架构及以上)。
数据加载瓶颈会导致GPU等待,间接加剧内存压力。优化方法:
DataLoader的num_workers参数(如设置为4或8),启用多进程数据加载;内存泄漏会导致显存持续增长,最终耗尽资源。常见问题及解决方法:
del output, loss);torch.cuda.empty_cache();nvidia-smi监控显存使用趋势,定位持续增长的内存占用。大型模型(如ResNet-152、VGG-19)参数多、显存占用大,可替换为轻量级模型(如MobileNet、EfficientNet、SqueezeNet)。这些模型通过深度可分离卷积、通道剪枝等技术,在保持相近性能的同时,显著减少内存占用。
若有多个GPU或多台机器,可将模型训练分散到多个设备上,降低单个设备的显存负载。使用torch.nn.parallel.DistributedDataParallel(DDP)实现高效的分布式训练,需注意:
torch.distributed.init_process_group);DDP对象;batch_size(总批量大小=单设备批量大小×GPU数量)。sudo echo 3 | sudo tee /proc/sys/vm/drop_caches命令,释放系统缓存(不影响PyTorch显存,但可增加可用系统内存);sudo dd if=/dev/zero of=/swapfile bs=64M count=16 # 创建64MB×16=1GB的交换文件
sudo mkswap /swapfile # 格式化为交换文件
sudo swapon /swapfile # 启用交换文件
# 永久生效:将`/swapfile none swap sw 0 0`添加到/etc/fstab
注意:交换文件性能远低于物理内存,仅作为临时解决方案。若上述软件优化均无法满足需求,需考虑升级硬件: