系列文章目录
项目信息、本地GPU单卡复现:
华为Ascend众智计划项目–3DMPPE_ROOTNET–Pytorch模型迁移至NPU(一)
模型迁移——本地代码添加:
华为Ascend众智计划项目–3DMPPE_ROOTNET–Pytorch模型迁移至NPU(二)
模型迁移——服务器GPU-2P调试和NPU单卡调试:
华为Ascend众智计划项目–3DMPPE_ROOTNET–Pytorch模型迁移至NPU(三)
模型迁移——NPU单P性能和精度调优:
华为Ascend众智计划项目–3DMPPE_ROOTNET–Pytorch模型迁移至NPU(四)
模型迁移——NPU-8P调试:
华为Ascend众智计划项目–3DMPPE_ROOTNET–Pytorch模型迁移至NPU(五)
文章目录
- 系列文章目录
- 前言
- 一、模型迁移——本地代码添加
- 1.添加prof、FPS、apex
- ①prof
- ②FPS
- ③Apex
- 2.添加DDP
- 总结
前言
本系列文章记录笔者在完成华为昇腾众智项目的主要过程、遇到的问题及解决方案等。Ascend 众智计划是华为围绕 Ascend 基础软件平台推出的一项生态合作计划,旨在汇聚高校、科研院所、企业等组织和机构的开发团队,通过项目合作方式,基于 Ascend 基础软硬件平台开发算子、网络模型及行业参考设计,不断丰富 Ascend 计算产业生态,为加速千行百业智能化升级贡献智慧与力量。笔者负责的是姿态识别模型3DMPPE_ROOTNET的训练任务,该模型是基于Pytorch框架实现的。
一、模型迁移——本地代码添加
本节内容主要对应的是华为文档中的模型迁移说明部分,请首先仔细阅读该部分文档。博客中的内容仅为作者进行实现的主要流程和问题解决方案,不会涉及具体教程。在代码修改过程中请注意代码备份以及文档中的要求。 如果遇到问题可以参照modelzoo中已经完成的模型,或及时进行咨询。这里给出几个可以参考的模型(均为NPU上的代码,可以参考)。resnet50 、resnet50_8p
1.添加prof、FPS、apex
①prof
- Pytorch中autograd 的 profiler 提供内视每个操作在GPU和CPU的花销,通过对生成的.prof文件进行分析可以发现耗时较为高的操作或存在问题的算子,从而进行替换或修改以提高性能。
- 注意prof仅用于调试、相当于Debug模式,想要得到prof文件,跑一个epoch即可。正常训练时不需要使用prof,在后续性能调优部分会有对prof文件的分析,使用prof会使代码运行时间大量提升。同时prof仅仅用于单卡,即一张GPU或NPU,如果在多卡环境下启用prof会导致RAM一直上升直到爆内存。
- 文档中给出的代码为:
with torch.autograd.profiler.profile(use_cuda=True) as prof: out = model(input_tensor)loss = loss_func(out)optimizer.zero_grad()if amp_mode:with amp.scale_loss(loss, optimizer) as scaled_loss:scaled_loss.backward()else:loss.backward()optimizer.step()
print(prof.key_averages().table(sort_by="self_cpu_time_total"))
prof.export_chrome_trace("output.prof") # "output.prof"为输出文件地址
- 为了方便后续在控制台运行代码,符合代码规范,可以添加if语句进行判断。
if cfg.use_prof:with torch.autograd.profiler.profile(use_npu=True) as prof:out = model(input_tensor)...# Train model
else:out = model(input_tensor)...# Train model
②FPS
FPS = BatchSize * num_devices / time_avg
- 请注意此处的time_avg不要统计每个epoch的前5个step的耗时,因为NPU前几个step会进行数据读取,较为耗时。time_avg可以可以使用以epoch为单位的平均耗时,需要去除前几个step加载数据带来的影响,统计类示例请参考AverageMeter
- 多卡运行时FPS部分的代码需要修改,具体会在后续阐释。
- 语言类请替换为对应统计方式。
③Apex
APEX是英伟达开源的,完美支持PyTorch框架,用于改变数据格式来减小模型显存占用的工具。其中最有价值的是amp(Automatic Mixed Precision),将模型的大部分操作都用Float16数据类型测试,一些特别操作仍然使用Float32。并且用户仅仅通过三行代码即可完美将自己的训练代码迁移到该模型。实验证明,使用Float16作为大部分操作的数据类型,并没有降低参数,在一些实验中,反而由于可以增大Batchsize,带来精度上的提升,以及训练速度上的提升。
(参考自CSDN博主「咆哮的阿杰」 原文链接)
- 华为文档中给出的代码为(引自Apex文档):
# Declare model and optimizer as usual, with default (FP32) precision
model = torch.nn.Linear(D_in, D_out).cuda()
optimizer = torch.optim.SGD(model.parameters(), lr=1e-3)# Allow Amp to perform casts as required by the opt_level
# 注意,amp.initialize必须在DDP(DistributedDataParallel)之前,否则多卡时会有报错提示
model, optimizer = amp.initialize(model, optimizer, opt_level="O2",loss_scale=128.0)
...
# loss.backward() becomes:
with amp.scale_loss(loss, optimizer) as scaled_loss:scaled_loss.backward()
...
推荐优先使用 opt_level=‘O2’, loss_scale=128.0 的配置进行amp.initialize 若无法收敛推荐使用
opt_level=‘O1’, loss_scale=128.0 的配置进行amp.initialize 若依然无法收敛推荐使用
opt_level=‘O1’, loss_scale=None 的配置进行amp.initialize
- 实际运行过程中,O2相较于O1可以带来性能上更多的提升,但也会对应地损失一些精度,如果不确定loss_scale也可以,也可以将其设置为-1,表示动态,系统会自动调整。关于opt_level和loss_scale的调整会在后续性能和精度优化部分进行阐述。
- 添加完上述三个主要部分后,需要再次在本地进行代码调试和运行,复现论文的精度,正常情况下在添加了apex后,性能会有所提升,精度会略有下降。笔者的代码原先在本地单卡GPU正常情况下1个epoch需要3-4h,添加了apex后需要2h左右,如果在prof模式下5-6h。
2.添加DDP
- DDP部分华为文档中给出的内容较少,具体可以参考这篇博客进行代码修改。
DDP及其在pytorch中应用
另外推荐在DDP代码主体部分添加完成后,按照这篇博客中的教程,添加mp.spawn,从而避免使用torch.distributed.launch运行多卡代码,方面后续操作。 - 多卡代码修改完成后无法在本地单卡环境下进行调试,需要租用多卡GPU进行调试。
总结
本文介绍了模型迁移过程中本地添加代码的过程、主要包括prof、FPS、Apex和DDP。