CentOS系统下PyTorch内存管理优化策略
在优化前需先定位内存瓶颈,常用工具包括:
free -m查看系统整体内存(总内存、已用、可用);top或htop按%MEM排序,识别占用高的进程;nvidia-smi(GPU环境)监控GPU显存使用率及进程详情。torch.cuda.memory_summary()打印当前GPU内存分配详情(如已用/预留显存、张量数量);torch.cuda.empty_cache()后再次调用可对比释放效果。批次大小直接影响内存消耗(如ResNet-50训练时,batch_size从64减至32可使显存占用减半),但需权衡训练速度与模型精度(过小的批次可能导致泛化性能下降)。
通过自动混合精度训练(AMP),用FP16替代FP32进行计算(保留FP32主权重以维持数值稳定性),可减少50%以上显存占用且几乎不影响精度。
实现步骤:
from torch.cuda.amp import autocast, GradScaler
scaler = GradScaler() # 梯度缩放器(防止FP16下溢)
for inputs, targets in dataloader:
optimizer.zero_grad()
with autocast(): # 自动选择FP16/FP32计算
outputs = model(inputs)
loss = criterion(outputs, targets)
scaler.scale(loss).backward() # 缩放梯度避免溢出
scaler.step(optimizer) # 更新参数
scaler.update() # 调整缩放因子
del删除不再使用的张量(如中间结果、旧批次数据);torch.cuda.empty_cache()释放GPU缓存中未被引用的显存(注意:此操作会阻塞进程,频繁调用可能影响性能);torch.no_grad()上下文管理器,禁用梯度计算以减少内存占用(如验证集评估时)。通过多次小批次计算梯度并累加,最后再进行一次参数更新,模拟大批次训练效果(如batch_size=32,累积4次相当于128的批量效果),适用于显存不足的场景。
代码示例:
accumulation_steps = 4
for i, (inputs, targets) in enumerate(dataloader):
outputs = model(inputs)
loss = criterion(outputs, targets) / accumulation_steps # 损失缩放
loss.backward() # 累积梯度
if (i + 1) % accumulation_steps == 0:
optimizer.step() # 更新参数
optimizer.zero_grad() # 清零梯度
将模型训练分配到多个GPU(DataParallel或DistributedDataParallel)或多台机器,降低单机内存压力。推荐使用DistributedDataParallel(DDP),其效率更高且支持多机多卡。
关键步骤:
torch.distributed.init_process_group(backend='nccl');model = DDP(model, device_ids=[local_rank]);torchrun命令(如torchrun --nproc_per_node=4 train.py)。DataLoader的num_workers参数(建议2-4,根据CPU核心数调整),启用多进程数据加载,避免主线程阻塞;torch.utils.data.Subset仅加载所需数据子集(如调试时),或torch.utils.data.BatchSampler自定义批量策略(如动态调整批次大小)。内存泄漏会导致内存持续增长,常见原因及解决方法:
torch.no_grad(),导致计算图未被释放;with torch.no_grad():。del删除,或变量间存在循环引用;del tensor删除无用张量,配合gc.collect()手动触发垃圾回收。num_workers > 0时,非Tensor输入(如numpy数组)可能因“copy-on-access”导致内存复制;torch.from_numpy(array))或使用tolist()转换。sudo fallocate -l 8G /swapfile # 创建8G交换文件
sudo chmod 600 /swapfile # 设置权限
sudo mkswap /swapfile # 格式化为Swap
sudo swapon /swapfile # 启用Swap
echo '/swapfile swap swap defaults 0 0' | sudo tee -a /etc/fstab # 开机自启