PyTorch DDP单机多GPU训练:训练与测试精度差异问题
问题原因及解决步骤
这种差异几乎肯定是训练循环内的精度计算逻辑没有适配DDP的分布式环境导致的,核心是你没正确统计全局的训练样本和正确预测数,具体原因和修复方法如下:
未同步各GPU的统计数据
DDP中每个GPU只处理全局batch的一个子集,如果你在每个GPU上单独计算准确率再取平均,得到的结果和全局真实准确率会有偏差(极端情况下就会出现你这种极低的数值)。正确的做法是:- 每个GPU计算自己的局部正确预测数(
correct_local)和局部样本数(total_local) - 使用
torch.distributed.all_reduce把所有GPU的correct_local和total_local汇总到主GPU(或所有GPU) - 用汇总后的总数计算全局训练准确率,而不是直接平均各GPU的准确率
示例代码片段:
# 每个GPU计算局部统计 pred = torch.argmax(output, dim=1) correct_local = pred.eq(target).sum() total_local = target.size(0) # 同步所有GPU的统计值 torch.distributed.all_reduce(correct_local, op=torch.distributed.ReduceOp.SUM) torch.distributed.all_reduce(total_local, op=torch.distributed.ReduceOp.SUM) # 计算全局准确率(仅主GPU打印即可) if torch.distributed.get_rank() == 0: train_acc = correct_local.item() / total_local.item() print(f"Train Accuracy: {train_acc:.4f}")- 每个GPU计算自己的局部正确预测数(
训练时计算精度未处理BN层的行为
训练循环内模型处于train()模式,BN层会使用当前batch的均值和方差,而测试时模型切换到eval()模式用累计的全局统计值。如果你的训练精度计算逻辑没有暂时切换模型模式,可能会因为BN层的不稳定输出导致预测结果偏差(虽然这个影响通常不会这么极端,但也是潜在因素)。修复方法是:
在计算训练精度前临时切换到eval()模式,计算完成后切回train():model.eval() with torch.no_grad(): # 计算训练精度的代码 ... model.train()误将单GPU的局部结果当作全局结果
如果你只打印了主GPU的局部准确率,而主GPU恰好分到了难分类的样本子集,就会出现看似全局精度极低的情况。但你说的是8块GPU平均后的结果,所以更可能是第一种同步问题。
另外,确认你保存模型时是用model.module.state_dict()(DDP封装后的模型要取module的参数),这点你已经做到了,因为测试精度正常,说明模型参数保存正确。
内容的提问来源于stack exchange,提问作者Arun
相关产品推荐
相关产品推荐

