3D_ResNet模型在迁移到昇腾AI处理器上训练后,发现Loss收敛效果较GPU出现异常。
在PyTorch模型迁移与训练过程中出现的精度问题,可以从以下两方面依次进行定位。
请参考ptdbg_ascend工具使用说明安装ptdbg_ascend精度工具。
cd src vi main.py
from ptdbg_ascend import register_hook, overflow_check, seed_all, set_dump_path, set_dump_switch, acc_cmp_dump
def main():
seed_all()
... def main():
...
model = create_model(opt.arch, opt.heads, opt.head_conv)
...
set_dump_path("./data/dump", dump_tag='npu_overflow') # 设置dump路径,最终数据保存在此路径下
register_hook(model, overflow_check, overflow_nums=1) # 使能溢出检测
...
for epoch in range(start_epoch + 1, opt.num_epochs + 1):
... bash ./test/train_full_1p.sh --data_path=数据集路径
def main():
...
model = create_model(opt.arch, opt.heads, opt.head_conv)
optimizer = torch.optim.Adam(model.parameters(), opt.lr)
...
set_dump_path("./dump_data_new/npu") # 设置dump路径,最终数据保存在此路径下
register_hook(model, acc_cmp_dump) # 添加hook函数和数据比对dump开关
for epoch in range(start_epoch + 1, opt.num_epochs + 1):
... set_dump_switch("ON")
for epoch in range(start_epoch + 1, opt.num_epochs + 1):
...
logger.write('\n')
set_dump_switch("OFF")
#NPU训练命令 bash ./test/train_full_1p.sh --data_path=数据集路径
模型训练结束后,数据会落盘到输出目录。样例输出目录如下图。
from ptdbg_ascend import compare
dump_result_param={
"npu_pkl_path": "./npu/rank0/dump.pkl"
"bench_pkl_path": "./cpu/rank0/dump.pkl"
"npu_dump_data_dir": "./npu/rank0/dump"
"bench_dump_data_dir": "./cpu/rank0/dump"
}
compare(dump_result_param,"./out") python3 compare.py
比对完成后会在指定的输出目录中生成对比结果文件“compare_result_timestamp.csv”,示例文件如下所示。
可以看到第一个存在问题的是iadd API的input_0,其余弦相似度小于0.99并且最大绝对值误差远大于0.001。
set_dump_switch("ON", mode="stack", scope=['Tensor___iadd___forward']) def forward(self, x):
residual = x
out = self.conv1(x)
out = self.bn1(out)
out = self.relu(out)
out = self.conv2(out)
out = self.bn2(out)
if self.downsample is not None:
residual = self.downsample(x)
out += residual # 问题代码行
out = self.relu(out)
因此根据以上结论,可以定位到是iadd的输出存在问题,而不是输入。
def forward(self, x):
residual = x
out = self.conv1(x)
out = self.bn1(out)
out = self.relu(out)
out = self.conv2(out)
out = self.bn2(out) # out为batchnorm的输出,代入到下方成为了自增操作的输入
if self.downsample is not None:
residual = self.downsample(x)
out += residual # 问题代码行
out = self.relu(out)
检视batchnorm算子的比对结果数据,如下图,可以确定batchnorm输出(即iadd真实输入)的余弦相似值为1,最大绝对值误差接近0,无精度问题。
因此可以得出结论:iadd算子的计算精度存在问题,导致iadd输出精度异常。可以联系华为工程师解决此问题,可进入昇腾开源社区使用issue进行沟通。