数据dump比对使用指南
单机单卡场景
- dump整网数据。分别dump CPU或GPU以及NPU数据,在PyTorch训练脚本插入dump接口,示例代码如下(下面以NPU为例,CPU或GPU dump基本相同):
from ptdbg_ascend import register_hook, overflow_check, seed_all, set_dump_path, set_dump_switch, acc_cmp_dump # 在main函数开始前固定随机数 seed_all() # 配置dump数据的.pkl文件名和路径 set_dump_path("./npu_dump.pkl", dump_tag='all') # 注册dump回调函数 register_hook(model, acc_cmp_dump) ... # 在第一个迭代开始的位置开启dump且不配置dump关闭,即dump整网数据,另外dump堆栈信息 set_dump_switch("ON", mode="api_stack")
dump文件目录结构如下,dump文件目录结构说明可参考dump文件目录结构。
all_v1.0 └── rank1 ├── api_stack_npu_dump │ ├── Functional_conv2d_0_forward_input.0.npy │ ├── Functional_conv2d_0_forward_output.npy │ ..... │ ├── Torch_relu__9_forward_input.0.npy │ └── Torch_relu__9_forward_output.npy └── api_stack_npu_dump.pkl
- 比对整网数据。创建并配置精度比对脚本,以创建compare.py为例,示例代码如下:
from ptdbg_ascend import register_hook, overflow_check, seed_all, set_dump_path, set_dump_switch, acc_cmp_dump dump_result_param={ "npu_pkl_path": "./api_stack_npu_dump.pkl", "bench_pkl_path": "./api_stack_gpu_dump.pkl", "npu_dump_data_dir": "./api_stack_npu_dump_20230104_13434", "bench_dump_data_dir": "./api_stack_gpu_dump_20230104_132544", "is_print_compare_log": True } compare(dump_result_param, "./output", True, stack_mode=True)
执行比对:python3 compare.py
- 找出存在问题的API。
在比对结果的csv文件中,通过对比dump出的数值,计算两者的余弦相似度、均方根误差和最大绝对误差,定位和排查NPU算子存在的计算精度问题。筛选出余弦相似度(Cosine)小于0.99,最大绝对值误差(MaxAbsError)大于0.001的第一个API,针对该API执行后续比对操作,分析该API存在的精度问题。以下图为例,发现第一个可能存在问题的API为67_VF_lstm_backward,则后续针对此API进行进一步dump。
图1 比对结果csv文件样例
- 提取指定API的堆栈信息和dump数据统计信息。
通过parse接口可以清晰的显示特定API的堆栈信息和dump数据统计信息,结合堆栈信息分析代码中可能存在的精度问题。
创建并配置提取脚本,以创建parse.py为例,示例代码如下:from ptdbg_ascend import register_hook, overflow_check, seed_all, set_dump_path, set_dump_switch, acc_cmp_dump # 提取dump信息中第1次调用的API:67_VF_lstm_backward的堆栈信息及数据统计信息 parse("./npu_dump.pkl", "67_VF_lstm_backward")
执行提取:python3 parse.py
回显类似如下,用户可根据回显中的Trace back堆栈信息分析可能存在的精度问题:
Statistic Info: [67_VF_lstm_backward_input.0][dtype: torch.float32][shape: [1, 3, 244, 244]][max: 4.149261951446533][min: -4.198638916015625][mean: 0.002332142787054181] [67_VF_lstm_backward_input.1][dtype: torch.float32][shape: [64, 3, 7, 7]][max: 0.1047200858592987][min: -0.10305210202932358][mean: 0.0004971990711055696] [67_VF_lstm_backward_output][dtype: torch.float32][shape: [1, 64, 122, 122]][max: 1.4602006673812866][min: -1.434123158454895][mean: -9.677638445282355e-05] Trace back(Functional_conv2d_0_forward_stack_info): File "npu_jd.py", line 35, in <module> output = model_npu(inputs) File "/usr/local/python3.7.5/lib/python3.7/site-packages/torch/nn/modules/module.py", line 1110, in _call_impl return forward_call(*input, **kwargs) File "/usr/local/python3.7.5/lib/python3.7/site-packages/torchvision/models/resnet.py", line 285, in forward return self._forward_impl(x) ... ... File "/usr/local/python3.7.5/lib/python3.7/site-packages/ptdbg_ascend/hooks/wrap_functional.py", line 59, in functional_op_template return FunctionalOPTemplate(op_name, hook)(*args, **kwargs) File "/usr/local/python3.7.5/lib/python3.7/site-packages/ptdbg_ascend/hooks/module.py", line 70, in __call__ hook_result = hook(self, input, result)
单机多卡场景
精度工具单机多卡场景下的精度比对步骤与单机单卡场景完全一致。唯一不同的是精度比对时需要使用compare_distributed函数进行比对:
- 创建比对脚本,例如compare_distributed.py。
from ptdbg_ascend import register_hook, overflow_check, seed_all, set_dump_path, set_dump_switch, acc_cmp_dump compare_distributed('npu_dump/dump_conv2d_v1.0', 'gpu_dump/dump_conv2d_v1.0', './output')
- 执行比对。
python3 compare_distributed.py
- 两次运行须用相同数量的卡,传入compare_distributed的两个文件夹下须有相同个数的rank文件夹,且不包含其他无关文件,否则将无法比对。
- 单机多卡一般为多进程,须保证每个进程都正确调用set_dump_path,或把set_dump_path插入到import语句后,如:
from ptdbg_ascend import register_hook, overflow_check, seed_all, set_dump_path, set_dump_switch, acc_cmp_dump seed_all() set_dump_path('./dump_resnet/myDump.pkl')
如此可保证set_dump_path在每个进程都被调用。
- register_hook需要在set_dump_path之后调用,也需要在每个进程上被调用,建议在搬运模型数据到卡之后调用。识别方法如下:
- 找到训练代码中遍历epoch的for循环或遍历数据集的for循环,把register_hook放到循环开始前即可。
- 找到训练代码中调用DDP或者DistributedDataParallel的代码行,把register_hook放到该代码行所在的代码块之后。
- 若代码中均无以上两种情况,需要保证register_hook在模型定义之后插入,并配置rank参数,示例如下:
register_hook(model, acc_cmp_dump, rank=rank_id)
父主题: 精度调优