在PyTorch混合精度模式下,每次迭代执行一次参数更新时,在Loss乘/除以缩放系数的过程中都会包含连续多个小算子(如add、mul、sqrt等)下发,由于小算子在NPU上计算快,导致算子在CPU上的下发成为性能的主要瓶颈。本调优案例以MobileNetV1模型为例,进行梯度融合调优解决此性能问题。
使用昇腾AI处理器亲和的融合优化器替换原始优化器,本例中使用torch_npu.optim.NpuFusedSGD替换原始优化器torch.optim.SGD。昇腾AI处理器亲和的融合优化器可以在梯度更新过程中将连续多个小算子融合后下发,提升模型计算性能,完整融合优化器替换表请参见NPU亲和优化器替换。
点击获取链接,获取MobileNetV1模型,并根据readme准备训练环境和数据集。
从昇腾ModelZoo上获取的MobileNetV1模型脚本为已经进行了梯度融合优化的版本。若用户想使用该模型脚本体验本案例中的调优流程,可先将模型脚本main.py中的优化器定义代码改为原始优化器torch.optim.SGD,再执行以下流程。
model = model.to(device) # define loss function (criterion) and optimizer criterion = nn.CrossEntropyLoss().to(device) optimizer = torch.optim.SGD(model.parameters(), args.lr, momentum=args.momentum, weight_decay=args.weight_decay) if args.apex: model, optimizer = amp.initialize(model, optimizer, opt_level=args.apex_opt_level, loss_scale=args.loss_scale_value, combine_grad=True)
bash ./test/train_full_1p.sh --data_path=/data/path/ # 请根据实际情况更改data_path
耗时数据如所示。
以下调优步骤基于已完成模型向NPU的迁移。
import torch_npu import torch_npu.optim
optimizer = torch.optim.SGD(model.parameters(), args.lr, momentum=args.momentum, weight_decay=args.weight_decay)
optimizer = torch_npu.optim.NpuFusedSGD(model.parameters(), args.lr, momentum=args.momentum, weight_decay=args.weight_decay)
或
optimizer = apex.optimizers.NpuFusedSGD(model.parameters(), args.lr, momentum=args.momentum, weight_decay=args.weight_decay)
当前昇腾适配的MobileNetV1模型使用的是apex组件包中的NpuFusedSGD,此处修改为torch_npu.optim.NpuFusedSGD可能会导致精度异常。
bash ./test/train_full_1p.sh --data_path=/data/path/ # 请根据实际情况更改data_path
耗时数据如图2所示。