本样例采用E2E profiling方式进行数据采集。E2E profiling可以端到端地分析模型性能瓶颈所在,详见数据采集概述。进行profiling的详细样例步骤如下:
for i, (images, target) in enumerate(train_loader): # measure data loading time data_time.update(time.time() - end) # move data to the same device as model …… if i % args.print_freq == 0: progress.display(i + 1)
修改后代码如下:
for i, (images, target) in enumerate(train_loader): if i == 11: #运行10个step后再profiling模型训练一个step的数据 with torch_npu.npu.profile(profiler_result_path="./result",use_e2e_profiler=True): # measure data loading time data_time.update(time.time() - end) # move data to the same device as model …… if i % args.print_freq == 0: progress.display(i + 1) else: #正常执行模型训练过程 # measure data loading time data_time.update(time.time() - end) # move data to the same device as model …… if i % args.print_freq == 0: progress.display(i + 1)
python3 main.py /home/data/resnet50/imagenet --batch-size 1024 \ # 训练批次大小 --lr 0.8 \ # 学习率 --epochs 90 \ # 训练迭代轮数 --arch shufflenet_v2_x1_0 \ # 模型架构 --world-size 1 \ --rank 0 \ --workers 40 \ # 加载数据进程数 --momentum 0.9 \ # 动量 --weight-decay 1e-4 # 权重衰减 --gpu 0 # device号, 这里参数名称仍为gpu, 但迁移完成后实际训练设备已在代码中定义为npu
/usr/local/Ascend/ascend-toolkit/latest/toolkit/tools/profiler/bin/msprof --export=on --output=./
针对上述NPU性能瓶颈,需要参考《AOE工具使用指南》进行AOE自动调优。本样例中具体AOE调优步骤如下:
# switch to train mode model.train() end = time.time() #如果为PyTorch1.5版本,请使用torch.npu.set_aoe(dump_path),dump_path为保存算子子图的路径,请自行设置 torch_npu.npu.set_aoe(dump_path) for i, (images, target) in enumerate(train_loader): if i > 0: #只需要运行一个step exit() if i > 100: pass ……
export TUNE_BANK_PATH=bank_path
更多环境变量说明可参见《AOE工具使用指南》“PyTorch训练场景下调优>算子调优”章节中的“配置环境变量”小节。
aoe --job_type=2 --model_path=dump_path #dump_path为保存算子子图的路径
执行调优后,将逐个打印算子调优完成情况,完成后打印调优总耗时,如下所示:
[Aoe]<xxxx> Single operator tuning process finished. //xxxx:算子名称。 [Aoe]Aoe process finished,cost time ***s. //调优完成,***为调优耗时。
export TUNE_BANK_PATH=bank_path #使能知识库 export ENABLE_TUNE_BANK=True
[ { "basic": { "tuning_name": "ge_proto_00274_MatMul", "tuning_time(s)": 129 } }, { "OPAT": { "opat_tune_result": "tune success", "repo_modified_operators": { "add_repo_operators": [ { "op_name": "MatMul", #算子名称。 "op_type": "MatMul", #算子类型。 "performance_after_tune(us)": 16.95, #调优后算子执行时间,单位:us。 "performance_before_tune(us)": 77.508, #调优前算子执行时间,单位:us。 "performance_improvement": "78.13%" #调优后算子执行时间减少百分比。 } ] }, "repo_summary": { "repo_add_num": 1, "repo_hit_num": 0, "repo_reserved_num": 0, "repo_unsatisfied_num": 0, "repo_update_num": 0, "total_num": 1 } } } ]
在以上算子样例中,MatMul算子成功调优后执行时间减少了78.13%,提升了模型运行性能。
更多对算子调优结果文件的字段解释可参见《AOE工具使用指南》“PyTorch训练场景下调优>查看调优结果”章节。
针对上述小算子过多瓶颈,为了优化性能,需要替换亲和函数减少梯度更新阶段的Add、Mul算子调用数量。
样例原代码如下:
optimizer = torch.optim.SGD(model.parameters(), args.lr, momentum=args.momentum, weight_decay=args.weight_decay)
样例修改后代码如下:
optimizer = apex.optimizers.NpuFusedSGD(model.parameters(), lr=args.lr, momentum=args.momentum, weight_decay=args.weight_decay)