From f3bf8d89125ce46110aeefd23a8398bfaa0ff33b Mon Sep 17 00:00:00 2001 From: pengzirong Date: Wed, 17 Jan 2024 09:23:50 +0800 Subject: [PATCH 1/4] =?UTF-8?q?[ptdbg=5Fascend]=E7=B2=BE=E5=BA=A6=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E8=B5=84=E6=96=99=E4=B8=BB=E6=8E=A8debugger=E6=95=B4?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...0\203\275\350\257\264\346\230\216_v4.0.md" | 81 +++++++++---------- 1 file changed, 37 insertions(+), 44 deletions(-) diff --git "a/debug/accuracy_tools/ptdbg_ascend/doc/ptdbg_ascend\347\262\276\345\272\246\345\267\245\345\205\267\345\212\237\350\203\275\350\257\264\346\230\216_v4.0.md" "b/debug/accuracy_tools/ptdbg_ascend/doc/ptdbg_ascend\347\262\276\345\272\246\345\267\245\345\205\267\345\212\237\350\203\275\350\257\264\346\230\216_v4.0.md" index 23ee300d25..dba8be4911 100644 --- "a/debug/accuracy_tools/ptdbg_ascend/doc/ptdbg_ascend\347\262\276\345\272\246\345\267\245\345\205\267\345\212\237\350\203\275\350\257\264\346\230\216_v4.0.md" +++ "b/debug/accuracy_tools/ptdbg_ascend/doc/ptdbg_ascend\347\262\276\345\272\246\345\267\245\345\205\267\345\212\237\350\203\275\350\257\264\346\230\216_v4.0.md" @@ -85,10 +85,10 @@ PyTorch训练场景的精度问题分析建议参考以下思路进行精度比 ```python from ptdbg_ascend import * dump_result_param={ - "npu_pkl_path": "./npu_dump/all_v2.0/rank0/api_stack_dump.pkl", - "bench_pkl_path": "./gpu_dump/all_v2.0/rank0/api_stack_dump.pkl", - "npu_dump_data_dir": "./npu_dump/all_v2.0/rank0/api_stack_dump", - "bench_dump_data_dir": "./gpu_dump/all_v2.0/rank0/api_stack_dump", + "npu_pkl_path": "./npu_dump/all_v4.0/step0/rank0/api_stack_dump.pkl", + "bench_pkl_path": "./gpu_dump/all_v4.0/step0/rank0/api_stack_dump.pkl", + "npu_dump_data_dir": "./npu_dump/all_v4.0/step0/rank0/api_stack_dump", + "bench_dump_data_dir": "./gpu_dump/all_v4.0/step0/rank0/api_stack_dump", "is_print_compare_log": True } compare(dump_result_param, "./output", stack_mode=True) @@ -120,7 +120,7 @@ PyTorch训练场景的精度问题分析建议参考以下思路进行精度比 from ptdbg_ascend import * # 提取dump信息中第1次调用的API:Torch_batch_normal的堆栈信息及数据统计信息 - parse("./npu_dump/all_v2.0/rank0/api_stack_dump.pkl", "Torch_batch_normal_1_forward") + parse("./npu_dump/all_v4.0/step0/rank0/api_stack_dump.pkl", "Torch_batch_normal_1_forward") ``` 执行提取: @@ -163,7 +163,7 @@ PyTorch训练场景的精度问题分析建议参考以下思路进行精度比 # dump指定反向API的ACL级别数据、bool和整型的tensor以及浮点、bool和整型的标量 set_dump_switch("ON", mode="acl", scope=["Functional_conv2d_1_backward"], filter_switch="OFF") - set_backward_input(["./npu_dump/all_v2.0/rank0/api_stack_dump/Functional_conv2d_1_backward_input.0.npy"]) + set_backward_input(["./npu_dump/all_v4.0/step0/rank0/api_stack_dump/Functional_conv2d_1_backward_input.0.npy"]) ... @@ -185,20 +185,13 @@ PyTorch训练场景的精度问题分析建议参考以下思路进行精度比 说明:多机多卡场景需要每个设备单独执行比对操作。 -假设NPU dump npy数据目录为npu_dump/dump_conv2d_v3.0,GPU dump npy数据目录为gpu_dump/dump_conv2d_v3.0。 +假设NPU dump npy数据目录为npu_dump/dump_conv2d_v4.0,GPU dump npy数据目录为gpu_dump/dump_conv2d_v4.0。 1. 创建比对脚本,例如compare_distributed.py,拷贝如下代码。 ```python from ptdbg_ascend import * - compare_distributed('./npu_dump/dump_conv2d_v3.0', './gpu_dump/dump_conv2d_v3.0', './output') - ``` - - 若使用debugger方式dump数据,且配置了PrecisionDebugger模块的step参数,则compare_distributed指定到step目录层级,如下示例: - - ```python - from ptdbg_ascend import * - compare_distributed('./npu_dump/step0', './gpu_dump/step0', './output') + compare_distributed('./npu_dump/dump_conv2d_v4.0', './gpu_dump/dump_conv2d_v4.0', './output') ``` 2. 执行比对: @@ -395,7 +388,7 @@ set_dump_switch("ON", mode="api_list", api_list=["distributed"]) # dump指定反向API的ACL级别溢出数据 register_hook(model, acc_cmp_dump, dump_mode='acl', dump_config='./dump.json') set_dump_switch("ON", mode="acl", scope=["Functional_conv2d_1_backward"]) - set_backward_input(["./npu_dump/ptdbg_dump_v2.0/rank0/dump/Functional_conv2d_1_backward_input.0.npy"]) + set_backward_input(["./npu_dump/ptdbg_dump_v4.0/step0/rank0/dump/Functional_conv2d_1_backward_input.0.npy"]) ``` 针对前向溢出API,可以通过overflow_nums,配置允许的溢出次数,并将每次溢出API的全部ACL数据dump下来,到达指定溢出次数后停止,停止后会看到堆栈打印包含如下字段。 @@ -501,42 +494,42 @@ configure_hook可配置多种dump模式,示例如下: - 示例1:dump指定API列表 ```python - debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="dump", step=[0]) + debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="dump", step=[0], enable_dataloader=True) debugger.configure_hook(mode="list", scope=["Tensor_permute_1_forward", "Tensor_transpose_2_forward", "Torch_relu_3_backward"]) ``` - 示例2:dump指定范围 ```python - debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="dump", step=[0]) + debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="dump", step=[0], enable_dataloader=True) debugger.configure_hook(mode="range", scope=["Tensor_abs_1_forward", "Tensor_transpose_3_forward"]) ``` - 示例3:STACK模式,只dump堆栈信息 ```python - debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="dump", step=[0]) + debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="dump", step=[0], enable_dataloader=True) debugger.configure_hook(mode="stack", scope=["Tensor_abs_1_forward", "Tensor_transpose_3_forward"]) ``` - 示例4:dump指定前向API的ACL级别数据 ```python - debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="dump", step=[0]) + debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="dump", step=[0], enable_dataloader=True) debugger.configure_hook(mode="acl", scope=["Tensor_permute_1_forward"], acl_config="./dump.json") ``` - 示例5:dump指定反向API的ACL级别数据 ```python - debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="dump", step=[0]) - debugger.configure_hook(mode="acl", scope=["Functional_conv2d_1_backward"], acl_config="./dump.json", backward_input=["./npu_dump/dump_conv2d_v2.0/rank0/dump/Functional_conv2d_1_backward_input.0.npy"]) + debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="dump", step=[0], enable_dataloader=True) + debugger.configure_hook(mode="acl", scope=["Functional_conv2d_1_backward"], acl_config="./dump.json", backward_input=["./npu_dump/ptdbg_dump_v4.0/step0/rank0/api_stack_dump/Functional_conv2d_1_backward_input.0.npy"]) ``` - 示例6:dump指定某一类API的API级别输入输出数据 ```python - debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="dump", step=[0]) + debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="dump", step=[0], enable_dataloader=True) debugger.configure_hook(mode="api_list", api_list=["relu"]) ``` @@ -545,7 +538,7 @@ configure_hook可配置多种dump模式,示例如下: - 示例7:dump全部API级别输入输出数据以及相应堆栈信息 ```python - debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="dump", step=[0]) + debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="dump", step=[0], enable_dataloader=True) debugger.configure_hook(mode="api_stack") ``` @@ -554,7 +547,7 @@ configure_hook可配置多种dump模式,示例如下: - 示例8: dump全部API级别输入输出数据并包含bool和整型的tensor以及浮点、bool和整型的标量,配置为OFF,会dump bool和整型数据 ```python - debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="dump", step=[0]) + debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="dump", step=[0], enable_dataloader=True) debugger.configure_hook(filter_switch="OFF") ``` @@ -563,21 +556,21 @@ configure_hook可配置多种dump模式,示例如下: - 示例9:仅保存dump的数据文件名包含“backward”的反向.npy文件 ```python - debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="dump", step=[0]) + debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="dump", step=[0], enable_dataloader=True) debugger.configure_hook(input_output_mode=["backward"]) ``` - 示例10:仅dump pkl文件 ```python - debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="dump", step=[0]) + debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="dump", step=[0], enable_dataloader=True) debugger.configure_hook(summary_only=True) ``` - 示例11:溢出检测dump ```python - debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="overflow_check", step=[0]) + debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="overflow_check", step=[0], enable_dataloader=True) debugger.configure_hook(overflow_nums=1) ``` @@ -590,7 +583,7 @@ configure_hook可配置多种dump模式,示例如下: - 示例11:dump溢出API的ACL级别数据 ```python - debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="overflow_check", step=[0]) + debugger = PrecisionDebugger(dump_path="./dump_path", hook_name="overflow_check", step=[0], enable_dataloader=True) debugger.configure_hook(mode="acl", acl_config="./dump.json") ``` @@ -670,7 +663,7 @@ debugger.stop() debugger.stop() debugger.start() - # 需要dump的代码片段1 + # 需要dump的代码片段2 debugger.stop() debugger.step() @@ -692,7 +685,7 @@ debugger.stop() debugger.stop() debugger.start() - # 需要dump的代码片段1 + # 需要dump的代码片段2 debugger.stop() debugger.step() @@ -968,7 +961,7 @@ set_dump_switch可配置多种dump模式,示例如下: ```python register_hook(model, acc_cmp_dump, dump_mode='acl', dump_config='./dump.json') set_dump_switch("ON", mode="acl", scope=["Functional_conv2d_1_backward"]) - set_backward_input(["./npu_dump/dump_conv2d_v2.0/rank0/dump/Functional_conv2d_1_backward_input.0.npy"]) + set_backward_input(["./npu_dump/dump_conv2d_v4.0/step0/rank0/dump/Functional_conv2d_1_backward_input.0.npy"]) ``` 需要配置register_hook的dump_mode='acl'和dump_config配置文件,并通过set_backward_input设置反向API输入的.npy文件。 @@ -1123,7 +1116,7 @@ set_backward_input(backward_input) ```python register_hook(model, acc_cmp_dump, dump_mode='acl', dump_config='./dump.json') set_dump_switch("ON", mode="acl", scope=["Functional_conv2d_1_backward"]) -set_backward_input(["./npu_dump/dump_conv2d_v2.0/rank0/dump/Functional_conv2d_1_backward_input.0.npy"]) +set_backward_input(["./npu_dump/dump_conv2d_v4.0/step0/rank0/dump/Functional_conv2d_1_backward_input.0.npy"]) ``` ## dump.json配置文件说明 @@ -1362,8 +1355,8 @@ compare_distributed(npu_dump_dir, bench_dump_dir, output_path, **kwargs) | 参数名 | 说明 | 是否必选 | | -------------- | ------------------------------------------------------------ | -------- | -| npu_dump_dir | 配置NPU环境下的dump目录,即set_dump_path函数的dump_tag参数对应的目录名称。参数示例:'./npu_dump/dump_conv2d_v2.0'。 | 是 | -| bench_dump_dir | 配置CPU、GPU或NPU环境下的dump目录,即set_dump_path函数的dump_tag参数对应的目录名称。参数示例:'./gpu_dump/dump_conv2d_v2.0'。 | 是 | +| npu_dump_dir | 配置NPU环境下的dump目录。参数示例:'./npu_dump/ptdbg_dump_v4.0'。register_hook方式可通过set_dump_path函数的dump_tag参数修改该目录名称。 | 是 | +| bench_dump_dir | 配置CPU、GPU或NPU环境下的dump目录。参数示例:'./gpu_dump/ptdbg_dump_v4.0'。register_hook方式可通过set_dump_path函数的dump_tag参数修改该目录名称。 | 是 | | output_path | 配置比对结果csv文件存盘目录。需要预先创建output_path目录。参数示例:'./output'。文件名称基于时间戳自动生成,格式为:`compare_result_rank{npu_ID}-rank{cpu/gpu/npu_ID}_{timestamp}.csv`。 | 是 | | **kwargs | 支持compare的所有可选参数。 | 否 | @@ -1373,7 +1366,7 @@ compare_distributed(npu_dump_dir, bench_dump_dir, output_path, **kwargs) ```python from ptdbg_ascend import * -compare_distributed('./npu_dump/ptdbg_dump_v2.0', './gpu_dump/ptdbg_dump_v2.0', './output') +compare_distributed('./npu_dump/ptdbg_dump_v4.0', './gpu_dump/ptdbg_dump_v4.0', './output') ``` ### compare @@ -1392,9 +1385,9 @@ compare(input_param, output_path, stack_mode=False, auto_analyze=True, fuzzy_mat | 参数名 | 说明 | 是否必选 | | ------------ | ------------------------------------------------------------ | -------- | -| input_param | 配置dump数据文件及目录。配置参数包括:
- "npu_pkl_path":指定NPU dump目录下的.pkl文件。参数示例:"npu_pkl_path": "./npu_dump/ptdbg_dump_v2.0/rank0/api_stack_dump.pkl"。必选。
- "bench_pkl_path":指定CPU、GPU或NPU dump目录下的.pkl文件。参数示例:"bench_pkl_path": "./gpu_dump/ptdbg_dump_v2.0/rank0/api_stack_dump.pkl"。必选。
- "npu_dump_data_dir":"指定NPU dump目录下的dump数据目录。参数示例:"npu_dump_data_dir": "./npu_dump/ptdbg_dump_v2.0/rank0/api_stack_dump"。可选,仅比对pkl文件时不选。
- "bench_dump_data_dir":"指定CPU、GPU或NPU dump目录下的dump数据目录。参数示例:"npu_dump_data_dir": "./gpu_dump/ptdbg_dump_v2.0/rank0/api_stack_dump"。可选,仅比对pkl文件时不选。
- "is_print_compare_log":配置是否开启日志打屏。可取值True或False。可选。 | 是 | +| input_param | 配置dump数据文件及目录。配置参数包括:
- "npu_pkl_path":指定NPU dump目录下的.pkl文件。参数示例:"npu_pkl_path": "./npu_dump/ptdbg_dump_v4.0/step0/rank0/api_stack_dump.pkl"。必选。
- "bench_pkl_path":指定CPU、GPU或NPU dump目录下的.pkl文件。参数示例:"bench_pkl_path": "./gpu_dump/ptdbg_dump_v4.0/step0/rank0/api_stack_dump.pkl"。必选。
- "npu_dump_data_dir":"指定NPU dump目录下的dump数据目录。参数示例:"npu_dump_data_dir": "./npu_dump/ptdbg_dump_v4.0/step0/rank0/api_stack_dump"。可选,仅比对pkl文件时不选。
- "bench_dump_data_dir":"指定CPU、GPU或NPU dump目录下的dump数据目录。参数示例:"npu_dump_data_dir": "./gpu_dump/ptdbg_dump_v4.0/step0/rank0/api_stack_dump"。可选,仅比对pkl文件时不选。
- "is_print_compare_log":配置是否开启日志打屏。可取值True或False。可选。 | 是 | | output_path | 配置比对结果csv文件存盘目录。参数示例:'./output'。文件名称基于时间戳自动生成,格式为:`compare_result_{timestamp}.csv`。 | 是 | -| stack_mode | 配置stack_mode的开关。仅当dump数据时配置set_dump_switch的mode="api_stack"时需要开启。参数示例:stack_mode=True,默认为False。 | 否 | +| stack_mode | 配置stack_mode的开关。仅当dump数据时配置debugger.configure_hook或set_dump_switch的mode="api_stack"时需要开启。参数示例:stack_mode=True,默认为False。 | 否 | | auto_analyze | 自动精度分析,开启后工具自动针对比对结果进行分析,识别到第一个精度不达标节点(在比对结果文件中的“Accuracy Reached or Not”列显示为No),并给出问题可能产生的原因(打屏展示并生成advisor_{timestamp}.txt文件)。可取值True或False,参数示例:auto_analyze=False,默认为True。 | 否 | | fuzzy_match | 模糊匹配。开启后,对于网络中同一层级且命名仅调用次数不同的API,可匹配并进行比对。可取值True或False,参数示例:fuzzy_match=True,默认为False。 | 否 | @@ -1405,10 +1398,10 @@ compare(input_param, output_path, stack_mode=False, auto_analyze=True, fuzzy_mat ```python from ptdbg_ascend import * dump_result_param={ -"npu_pkl_path": "./npu_dump/ptdbg_dump_v2.0/rank0/api_stack_dump.pkl", -"bench_pkl_path": "./gpu_dump/ptdbg_dump_v2.0/rank0/api_stack_dump.pkl", -"npu_dump_data_dir": "./npu_dump/ptdbg_dump_v2.0/rank0/api_stack_dump", -"bench_dump_data_dir": "./gpu_dump/ptdbg_dump_v2.0/rank0/api_stack_dump", +"npu_pkl_path": "./npu_dump/ptdbg_dump_v4.0/step0/rank0/api_stack_dump.pkl", +"bench_pkl_path": "./gpu_dump/ptdbg_dump_v4.0/step0/rank0/api_stack_dump.pkl", +"npu_dump_data_dir": "./npu_dump/ptdbg_dump_v4.0/step0/rank0/api_stack_dump", +"bench_dump_data_dir": "./gpu_dump/ptdbg_dump_v4.0/step0/rank0/api_stack_dump", "is_print_compare_log": True } compare(dump_result_param, "./output", stack_mode=True) @@ -1434,7 +1427,7 @@ parse(pkl_file, moudule_name_prefix) | 参数名 | 说明 | 是否必选 | | ------------------- | ------------------------------------------------------------ | -------- | -| pkl_file | 指定dump数据文件中的pkl文件名。参数示例:"./npu_dump/ptdbg_dump_v2.0/rank0/dump.pkl"。 | 是 | +| pkl_file | 指定dump数据文件中的pkl文件名。参数示例:"./npu_dump/ptdbg_dump_v4.0/step0/rank0/dump.pkl"。 | 是 | | moudule_name_prefix | 指定待提取的API接口前缀。参数示例:"Torch_norm_1_forward"。 | 是 | **函数示例** @@ -1443,7 +1436,7 @@ parse(pkl_file, moudule_name_prefix) ```python from ptdbg_ascend import * -parse("./npu_dump/ptdbg_dump_v2.0/rank0/dump.pkl", "Torch_batch_normal_1_forward") +parse("./npu_dump/ptdbg_dump_v4.0/step0/rank0/dump.pkl", "Torch_batch_normal_1_forward") ``` ### 计算精度评价指标 -- Gitee From c42f1d6dacab4ce0d97dab0aa927f524c7c432c3 Mon Sep 17 00:00:00 2001 From: pengzirong Date: Wed, 17 Jan 2024 15:11:10 +0800 Subject: [PATCH 2/4] =?UTF-8?q?[ptdbg=5Fascend]=E7=B2=BE=E5=BA=A6=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E8=B5=84=E6=96=99=E4=B8=BB=E6=8E=A8debugger=E6=95=B4?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...0\203\275\350\257\264\346\230\216_v4.0.md" | 345 ++++++++++++++---- 1 file changed, 283 insertions(+), 62 deletions(-) diff --git "a/debug/accuracy_tools/ptdbg_ascend/doc/ptdbg_ascend\347\262\276\345\272\246\345\267\245\345\205\267\345\212\237\350\203\275\350\257\264\346\230\216_v4.0.md" "b/debug/accuracy_tools/ptdbg_ascend/doc/ptdbg_ascend\347\262\276\345\272\246\345\267\245\345\205\267\345\212\237\350\203\275\350\257\264\346\230\216_v4.0.md" index dba8be4911..089872449d 100644 --- "a/debug/accuracy_tools/ptdbg_ascend/doc/ptdbg_ascend\347\262\276\345\272\246\345\267\245\345\205\267\345\212\237\350\203\275\350\257\264\346\230\216_v4.0.md" +++ "b/debug/accuracy_tools/ptdbg_ascend/doc/ptdbg_ascend\347\262\276\345\272\246\345\267\245\345\205\267\345\212\237\350\203\275\350\257\264\346\230\216_v4.0.md" @@ -4,6 +4,8 @@ ptdbg_ascend工具的原理及安装请参见《[PyTorch精度工具](https://gitee.com/ascend/att/blob/master/debug/accuracy_tools/ptdbg_ascend/README.md)》。 +ptdbg_ascend工具主要支持PyTorch API精度数据dump、溢出检测、精度比对以及parse数据解析功能。其中dump和溢出检测功能支持使用debugger和register_hook方式进行精度数据的dump和溢出检测,推荐使用debugger方式。 + ## PyTorch精度比对总体流程 1. 准备CPU或GPU训练工程。 @@ -30,9 +32,9 @@ ptdbg_ascend工具的原理及安装请参见《[PyTorch精度工具](https://gi 11. 比对结果分析。 -## 场景化示例 +## 快速入门(debugger方式) -本章节主要介绍通过ptdbg_ascend工具进行精度比对和分析,主要使用“**CPU或GPU及NPU精度数据dump**”和“**CPU或GPU与NPU精度数据比对**”章节中介绍的ptdbg_ascend工具接口。 +本章节主要介绍通过ptdbg_ascend工具进行精度比对和分析,主要使用“**debugger方式dump和溢出检测**”和“**CPU或GPU与NPU精度数据比对**”章节中介绍的ptdbg_ascend工具接口。 ### 单卡场景精度比对 @@ -42,7 +44,7 @@ PyTorch训练场景的精度问题分析建议参考以下思路进行精度比 1. 整网比对:dump整网数据并进行精度比对,初步定位异常范围。 2. 缩小范围:根据Accuracy Reached or Not找出不符合精度标准的API。 -3. 范围比对:对不符合精度标准的API重新dump。 +3. 范围比对:对不符合精度标准的API重新dump详细信息。 4. 分析原因并优化:分析API精度不符合标准的原因并进行优化调整。 5. 整网比对:重新进行整网比对,判断优化后的API是否已符合精度标准以及是否出现新的精度问题。 6. 重复1~5步,直到不存在精度问题为止。 @@ -54,41 +56,26 @@ PyTorch训练场景的精度问题分析建议参考以下思路进行精度比 分别dump CPU或GPU以及NPU数据,在PyTorch训练脚本插入dump接口,示例代码如下(下面以NPU为例,CPU或GPU dump基本相同): ```python + # 需要保证用户训练代码是通过torch.utils.data.dataloader方式加载数据 from ptdbg_ascend import * - - # 在main函数开始前固定随机数 - seed_all() - - # 配置dump数据目录路径和名称 - set_dump_path("./npu_dump", dump_tag='all') - - # 注册dump回调函数 - register_hook(model, acc_cmp_dump) - - ... - - # 在第一个迭代开始的位置开启dump和堆栈模式,同时为保证数据完整性开启dump bool和整型的tensor以及浮点、bool和整型的标量 - set_dump_switch("ON", mode="api_stack", filter_switch="OFF") - - ... - - # 在第一个迭代结束的位置关闭dump - set_dump_switch("OFF") + debugger = PrecisionDebugger(dump_path="./npu_dump", hook_name="dump", step=[0], enable_dataloader=True) + debugger.configure_hook(mode="api_stack") + # 请勿将以上初始化流程插入到循环代码中 ``` 2. 比对整网数据。 - 第1步中的NPU dump数据文件为npu_dump.pkl,假设NPU dump npy数据目录为npu_dump,GPU dump数据文件为gpu_dump.pkl,GPU dump npy数据目录为gpu_dump。 + 第1步中的NPU dump数据目录为npu_dump,假设GPU dump数据目录为gpu_dump;dump将生成pkl数据文件api_stack_dump.pkl和npy数据目录api_stack_dump。 创建并配置精度比对脚本,以创建compare.py为例,示例代码如下: ```python from ptdbg_ascend import * dump_result_param={ - "npu_pkl_path": "./npu_dump/all_v4.0/step0/rank0/api_stack_dump.pkl", - "bench_pkl_path": "./gpu_dump/all_v4.0/step0/rank0/api_stack_dump.pkl", - "npu_dump_data_dir": "./npu_dump/all_v4.0/step0/rank0/api_stack_dump", - "bench_dump_data_dir": "./gpu_dump/all_v4.0/step0/rank0/api_stack_dump", + "npu_pkl_path": "./npu_dump/ptdbg_dump_v4.0/step0/rank0/api_stack_dump.pkl", + "bench_pkl_path": "./gpu_dump/ptdbg_dump_v4.0/step0/rank0/api_stack_dump.pkl", + "npu_dump_data_dir": "./npu_dump/ptdbg_dump_v4.0/step0/rank0/api_stack_dump", + "bench_dump_data_dir": "./gpu_dump/ptdbg_dump_v4.0/step0/rank0/api_stack_dump", "is_print_compare_log": True } compare(dump_result_param, "./output", stack_mode=True) @@ -120,7 +107,7 @@ PyTorch训练场景的精度问题分析建议参考以下思路进行精度比 from ptdbg_ascend import * # 提取dump信息中第1次调用的API:Torch_batch_normal的堆栈信息及数据统计信息 - parse("./npu_dump/all_v4.0/step0/rank0/api_stack_dump.pkl", "Torch_batch_normal_1_forward") + parse("./npu_dump/ptdbg_dump_v4.0/step0/rank0/api_stack_dump.pkl", "Torch_batch_normal_1_forward") ``` 执行提取: @@ -136,38 +123,19 @@ PyTorch训练场景的精度问题分析建议参考以下思路进行精度比 - dump指定前向API的ACL级别数据 ```python - from ptdbg_ascend import * - - # 固定随机数,开启确定性计算 - seed_all(mode=True) - set_dump_path("./dump_path", dump_tag='forward') - register_hook(model, acc_cmp_dump, dump_mode='acl', dump_config='./dump.json') - - # dump指定前向API的ACL级别数据、bool和整型的tensor以及浮点、bool和整型的标量 - set_dump_switch("ON", mode="acl", scope=["Tensor_permute_1_forward"], filter_switch="OFF") - - ... - - set_dump_switch("OFF") + # 需要保证用户训练代码是通过torch.utils.data.dataloader方式加载数据 + debugger = PrecisionDebugger(dump_path="./npu_dump", hook_name="dump", step=[0], enable_dataloader=True) + debugger.configure_hook(mode="acl", scope=["Tensor_permute_1_forward"], acl_config='./dump.json') ``` - dump指定反向API的ACL级别数据 ```python + # 需要保证用户训练代码是通过torch.utils.data.dataloader方式加载数据 from ptdbg_ascend import * - - # 固定随机数,开启确定性计算 - seed_all(mode=True) - set_dump_path("./dump_path", dump_tag='backward') - register_hook(model, acc_cmp_dump, dump_mode='acl', dump_config='./dump.json') - + debugger = PrecisionDebugger(dump_path="./npu_dump", hook_name="dump", step=[0], enable_dataloader=True) # dump指定反向API的ACL级别数据、bool和整型的tensor以及浮点、bool和整型的标量 - set_dump_switch("ON", mode="acl", scope=["Functional_conv2d_1_backward"], filter_switch="OFF") - set_backward_input(["./npu_dump/all_v4.0/step0/rank0/api_stack_dump/Functional_conv2d_1_backward_input.0.npy"]) - - ... - - set_dump_switch("OFF") + debugger.configure_hook(mode="acl", scope=["Functional_conv2d_1_backward"], acl_config="./dump.json", backward_input=["./npu_dump/ptdbg_dump_v4.0/step0/rank0/api_stack_dump/Functional_conv2d_1_backward_input.0.npy"]) ``` 6. (可选)重新比对。 @@ -179,19 +147,110 @@ PyTorch训练场景的精度问题分析建议参考以下思路进行精度比 * dump_mode="acl"场景下,会增加npu的内存消耗,请谨慎开启。 * 部分API存在调用嵌套关系,比如functional.batch_norm实际调用torch.batch_norm,该场景会影响acl init初始化多次,导致功能异常。 +### 溢出检测场景 + +溢出检测是针对NPU的PyTorch API,检测是否存在溢出的情况。当前仅支持识别aicore浮点溢出。 + +溢出检测原理:针对溢出阶段,开启acl dump模式,重新对溢出阶段执行,落盘数据。 + +建议按照如下步骤操作: + +1. 在NPU环境下安装ptdbg_ascend工具。 + +2. 在NPU训练脚本内插入ptdbg_ascend工具溢出检测接口。 + + - 示例1:全量溢出检测 + + ```python + # 需要保证用户训练代码是通过torch.utils.data.dataloader方式加载数据 + from ptdbg_ascend import * + debugger = PrecisionDebugger(dump_path="./overflow_dump", hook_name="overflow_check", step=[0], enable_dataloader=True) + debugger.configure_hook(overflow_nums=-1) + # 请勿将以上初始化流程插入到循环代码中 + ``` + + 多卡使用时各卡单独计算溢出次数。 + + - 示例2:dump指定前向API的ACL级别溢出数据 + + ```python + # 需要保证用户训练代码是通过torch.utils.data.dataloader方式加载数据 + from ptdbg_ascend import * + debugger = PrecisionDebugger(dump_path="./overflow_dump", hook_name="overflow_check", step=[0], enable_dataloader=True) + debugger.configure_hook(mode="acl", acl_config="./dump.json") + # 请勿将以上初始化流程插入到循环代码中 + ``` + + - 示例3:dump指定反向API的ACL级别的溢出数据 + + 1. 进行全量溢出检测 + + ```python + # 需要保证用户训练代码是通过torch.utils.data.dataloader方式加载数据 + from ptdbg_ascend import * + debugger = PrecisionDebugger(dump_path="./overflow_dump", hook_name="overflow_check", step=[0], enable_dataloader=True) + debugger.configure_hook(overflow_nums=-1) + # 请勿将以上初始化流程插入到循环代码中 + ``` + + 2. dump指定反向API的ACL级别的溢出数据 + + ```python + # 需要保证用户训练代码是通过torch.utils.data.dataloader方式加载数据 + from ptdbg_ascend import * + debugger = PrecisionDebugger(dump_path="./overflow_dump", hook_name="dump", step=[0], enable_dataloader=True) + debugger.configure_hook(mode="acl", scope=["Functional_conv2d_1_backward"], acl_config="./dump.json", backward_input=["./overflow_dump/ptdbg_dump_v4.0/step0/rank0/api_stack_dump/Functional_conv2d_1_backward_input.0.npy"]) + # 请勿将以上初始化流程插入到循环代码中 + ``` + + 针对前向溢出API,可以通过overflow_nums,配置允许的溢出次数,并将每次溢出API的全部ACL数据dump下来,到达指定溢出次数后停止,停止后会看到堆栈打印包含如下字段。 + + ```bash + ValueError: [overflow xxx times]: dump file is saved in 'xxxxx.pkl'. + ``` + + 其中xxx times为用户设置的次数,xxxxx.pkl为文件生成路径。 + +3. NPU环境下执行训练dump溢出数据。 + + 针对输入正常但输出存在溢出的API,会训练执行目录下将溢出的API信息dump并保存为`forward_info_{pid}.json`和`backward_info_{pid}.json`,通过 [Ascend模型精度预检工具](https://gitee.com/ascend/att/tree/master/debug/accuracy_tools/api_accuracy_checker)对json文件进行解析,输出溢出API为正常溢出还是非正常溢出,从而帮助用户快速判断。 + + 精度预检工具执行命令如下: + + ```bash + # 下载att代码仓后执行如下命令 + export PYTHONPATH=$PYTHONPATH:$ATT_HOME/debug/accuracy_tools/ + cd $ATT_HOME/debug/accuracy_tools/api_accuracy_checker/run_ut + python run_overflow_check.py -forward ./forward_info_0.json + ``` + + 反向过程溢出的API暂不支持精度预检功能。 + + 当重复执行溢出检测dump操作时,需要删除上一次dump目录下的溢出检测dump数据,否则将因重名而报错。 + +**注意事项** + +* dump_mode="acl"场景下,会增加npu的内存消耗,请谨慎开启。 +* 部分API存在调用嵌套关系,比如functional.batch_norm实际调用torch.batch_norm,该场景会影响acl init初始化多次,导致功能异常。 +* 混合精度动态loss scale场景下,正常训练会有"Gradient overflow. SKipping step"日志,添加溢出检测后日志消失,可以通过设置环境变量export OVERFLOW_DEBUG_MODE_ENABLE=1,并将register_hook位置调整amp.initialize之前解决。此功能需要cann包配套支持,不支持版本执行报错EZ3003。 + +## 场景化示例 + +本章节主要介绍通过ptdbg_ascend工具进行精度比对和分析,主要使用“**CPU或GPU及NPU精度数据dump**”和“**CPU或GPU与NPU精度数据比对**”章节中介绍的ptdbg_ascend工具接口。 + ### 多卡场景精度比对 精度工具支持多卡场景的精度比对,多卡场景的dump步骤与单卡场景完全一致,请参见“**单卡场景精度比对**”章节,不同的是多卡数据精度比对时需要使用“compare_distributed”函数进行比对。如下示例: 说明:多机多卡场景需要每个设备单独执行比对操作。 -假设NPU dump npy数据目录为npu_dump/dump_conv2d_v4.0,GPU dump npy数据目录为gpu_dump/dump_conv2d_v4.0。 +假设NPU dump npy数据目录为npu_dump/ptdbg_dump_v4.0,GPU dump npy数据目录为gpu_dump/ptdbg_dump_v4.0。 1. 创建比对脚本,例如compare_distributed.py,拷贝如下代码。 ```python from ptdbg_ascend import * - compare_distributed('./npu_dump/dump_conv2d_v4.0', './gpu_dump/dump_conv2d_v4.0', './output') + compare_distributed('./npu_dump/ptdbg_dump_v4.0', './gpu_dump/ptdbg_dump_v4.0', './output') ``` 2. 执行比对: @@ -204,7 +263,14 @@ PyTorch训练场景的精度问题分析建议参考以下思路进行精度比 **多卡set_dump_path注意事项** -多卡一般为多进程,须保证每个进程都正确调用set_dump_path,或把set_dump_path插入到import语句后,如: +多卡一般为多进程,须保证每个进程都正确调用PrecisionDebugger或set_dump_path,或把PrecisionDebugger或set_dump_path插入到import语句后,如: + +```python +from ptdbg_ascend import * +debugger = PrecisionDebugger(dump_path="./npu_dump", hook_name="dump", step=[0], enable_dataloader=True) +``` + +或 ```python from ptdbg_ascend import * @@ -289,6 +355,12 @@ register_hook需要在set_dump_path之后调用,也需要在每个进程上被 通信类API数据可以使用全量dump方式获取,若只dump通信类API数据,可以使用如下示例: +```python +debugger.configure_hook(mode="api_list", api_list=["distributed"]) +``` + +或 + ```python set_dump_switch("ON", mode="api_list", api_list=["distributed"]) ``` @@ -311,7 +383,152 @@ set_dump_switch("ON", mode="api_list", api_list=["distributed"]) | 12 | _reduce_scatter_base | | 13 | _all_gather_base | -### 溢出检测场景 +### 单卡场景精度比对(register_hook方式) + +**精度分析建议** + +PyTorch训练场景的精度问题分析建议参考以下思路进行精度比对和比对结果分析: + +1. 整网比对:dump整网数据并进行精度比对,初步定位异常范围。 +2. 缩小范围:根据Accuracy Reached or Not找出不符合精度标准的API。 +3. 范围比对:对不符合精度标准的API重新dump。 +4. 分析原因并优化:分析API精度不符合标准的原因并进行优化调整。 +5. 整网比对:重新进行整网比对,判断优化后的API是否已符合精度标准以及是否出现新的精度问题。 +6. 重复1~5步,直到不存在精度问题为止。 + +**精度分析示例** + +1. dump整网数据。 + + 分别dump CPU或GPU以及NPU数据,在PyTorch训练脚本插入dump接口,示例代码如下(下面以NPU为例,CPU或GPU dump基本相同): + + ```python + from ptdbg_ascend import * + + # 在main函数开始前固定随机数 + seed_all() + + # 配置dump数据目录路径和名称 + set_dump_path("./npu_dump", dump_tag='all') + + # 注册dump回调函数 + register_hook(model, acc_cmp_dump) + + ... + + # 在第一个迭代开始的位置开启dump和堆栈模式,同时为保证数据完整性开启dump bool和整型的tensor以及浮点、bool和整型的标量 + set_dump_switch("ON", mode="api_stack", filter_switch="OFF") + + ... + + # 在第一个迭代结束的位置关闭dump + set_dump_switch("OFF") + ``` + +2. 比对整网数据。 + + 第1步中的NPU dump数据文件为npu_dump.pkl,假设NPU dump npy数据目录为npu_dump,GPU dump数据文件为gpu_dump.pkl,GPU dump npy数据目录为gpu_dump。 + + 创建并配置精度比对脚本,以创建compare.py为例,示例代码如下: + + ```python + from ptdbg_ascend import * + dump_result_param={ + "npu_pkl_path": "./npu_dump/all_v4.0/step0/rank0/api_stack_dump.pkl", + "bench_pkl_path": "./gpu_dump/all_v4.0/step0/rank0/api_stack_dump.pkl", + "npu_dump_data_dir": "./npu_dump/all_v4.0/step0/rank0/api_stack_dump", + "bench_dump_data_dir": "./gpu_dump/all_v4.0/step0/rank0/api_stack_dump", + "is_print_compare_log": True + } + compare(dump_result_param, "./output", stack_mode=True) + ``` + + 执行比对: + + ```bash + python3 compare.py + ``` + + 在output目录下生成结果文件,包括:`compare_result_{timestamp}.csv`和`advisor_{timestamp}.txt` + +3. 找出存在问题的API。 + + 1. 根据`advisor_{timestamp}.txt`或打屏信息的提示,可找到存在精度问题的算子(Suspect Nodes)和专家建议(Expert Advice) + + ![auto_analyze_log](img/auto_analyze_log.png) + + 2. 根据第2步结果文件`compare_result_{timestamp}.csv`中的Accuracy Reached or No字段显示为NO的API,针对该API执行后续比对操作,分析该API存在的精度问题。 + +4. (可选)提取指定API的堆栈信息和dump数据统计信息。 + + 通过parse接口可以清晰的显示特定API的堆栈信息和dump数据统计信息,结合堆栈信息分析代码中可能存在的精度问题。 + + 创建并配置提取脚本,以创建parse.py为例,示例代码如下: + + ```python + from ptdbg_ascend import * + + # 提取dump信息中第1次调用的API:Torch_batch_normal的堆栈信息及数据统计信息 + parse("./npu_dump/all_v4.0/step0/rank0/api_stack_dump.pkl", "Torch_batch_normal_1_forward") + ``` + + 执行提取: + + ```bash + python3 parse.py + ``` + + + +5. (可选)指定API对其底层ACL数据进行dump。 + + - dump指定前向API的ACL级别数据 + + ```python + from ptdbg_ascend import * + + # 固定随机数,开启确定性计算 + seed_all(mode=True) + set_dump_path("./dump_path", dump_tag='forward') + register_hook(model, acc_cmp_dump, dump_mode='acl', dump_config='./dump.json') + + # dump指定前向API的ACL级别数据、bool和整型的tensor以及浮点、bool和整型的标量 + set_dump_switch("ON", mode="acl", scope=["Tensor_permute_1_forward"], filter_switch="OFF") + + ... + + set_dump_switch("OFF") + ``` + + - dump指定反向API的ACL级别数据 + + ```python + from ptdbg_ascend import * + + # 固定随机数,开启确定性计算 + seed_all(mode=True) + set_dump_path("./dump_path", dump_tag='backward') + register_hook(model, acc_cmp_dump, dump_mode='acl', dump_config='./dump.json') + + # dump指定反向API的ACL级别数据、bool和整型的tensor以及浮点、bool和整型的标量 + set_dump_switch("ON", mode="acl", scope=["Functional_conv2d_1_backward"], filter_switch="OFF") + set_backward_input(["./npu_dump/all_v4.0/step0/rank0/api_stack_dump/Functional_conv2d_1_backward_input.0.npy"]) + + ... + + set_dump_switch("OFF") + ``` + +6. (可选)重新比对。 + + 根据第4或5步的dump数据重新配置compare.py并执行比对,可以对单API模型进行问题复现。 + +**注意事项** + +* dump_mode="acl"场景下,会增加npu的内存消耗,请谨慎开启。 +* 部分API存在调用嵌套关系,比如functional.batch_norm实际调用torch.batch_norm,该场景会影响acl init初始化多次,导致功能异常。 + +### 溢出检测场景(register_hook方式) 溢出检测是针对NPU的PyTorch API,检测是否存在溢出的情况。当前仅支持识别aicore浮点溢出。 @@ -489,7 +706,11 @@ debugger.configure_hook(mode=None, acl_config=None, overflow_nums=1, need_replic configure_hook可配置多种dump模式,示例如下: -说明:以下均以dump部分API数据为例,API名可以从首次dump整网数据的结果csv文件中的NPU Name或Bench Name列获取。 +说明: + +以下均以dump部分API数据为例,API名可以从首次dump整网数据的结果csv文件中的NPU Name或Bench Name列获取。 + +以下示例均以自动模式dump指定step数据为例,需要保证用户训练代码是通过torch.utils.data.dataloader方式加载数据。 - 示例1:dump指定API列表 @@ -625,7 +846,7 @@ debugger.stop() ### 示例代码(自动模式) -需要保证用户训练代码是通过torch.utils.data.dataloader方式加载数据。 +**需要保证用户训练代码是通过torch.utils.data.dataloader方式加载数据。** - 示例1:开启dump @@ -1313,10 +1534,10 @@ dump过程中,npy文件在对应算子或者模块被执行后就会落盘, **溢出检测dump场景** -PrecisionDebugger模块的hook_name参数或register_hook函数设置了overflow_check时,检测API溢出,dump结果的文件名格式为:`{api_type}___{api_name}___{API调用次数}_{前向反向}_{当前溢出次数}`,dump结果示例如下: +PrecisionDebugger模块的hook_name参数或register_hook函数设置了overflow_check时,检测API溢出,dump结果的文件名格式为:`{api_type}_{api_name}_{API调用次数}_{前向反向}_{当前溢出次数}`,dump结果示例如下: -* `Tensor___add___1_forward_1.pkl` -* `Tensor___add___1_forward_1`目录 +* `Tensor_add_1_forward_1.pkl` +* `Tensor_add_1_forward_1`目录 ## CPU或GPU与NPU精度数据比对 -- Gitee From 0e32787219ed5b6b463063437b894de3b00ce7ea Mon Sep 17 00:00:00 2001 From: pengzirong Date: Wed, 17 Jan 2024 17:16:47 +0800 Subject: [PATCH 3/4] =?UTF-8?q?[ptdbg=5Fascend]=E7=B2=BE=E5=BA=A6=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E8=B5=84=E6=96=99=E6=AF=94=E5=AF=B9=E5=8E=9F=E7=90=86?= =?UTF-8?q?=E5=9B=BE=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- debug/accuracy_tools/ptdbg_ascend/README.md | 2 +- .../ptdbg_ascend/figures/module_compare.png | Bin 56655 -> 39292 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/debug/accuracy_tools/ptdbg_ascend/README.md b/debug/accuracy_tools/ptdbg_ascend/README.md index f9ca19daf7..d753e7bb9b 100644 --- a/debug/accuracy_tools/ptdbg_ascend/README.md +++ b/debug/accuracy_tools/ptdbg_ascend/README.md @@ -83,7 +83,7 @@ ptdbg_ascend为PyTorch精度工具,用来进行PyTorch整网API粒度的数据 图1:精度比对逻辑图 - ![op_compare](figures/module_compare.png) + ![](figures/module_compare.png) **API匹配条件** diff --git a/debug/accuracy_tools/ptdbg_ascend/figures/module_compare.png b/debug/accuracy_tools/ptdbg_ascend/figures/module_compare.png index 2e1ea564eb191807034afd8aceac92b29b62a086..7262751b27a175a28098a145c883f22ee905e884 100644 GIT binary patch literal 39292 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 CYG=Rz literal 56655 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 z z;cpE6&M`PQf7QmOo;&5U+q3N_@3BvjbX$uE$|SI+d@B!b52K+n{rgA?jATB%`?T>Q zo%cl=>*}4;1Mfj9)(je~UjF@NJS{M8dBMTcY*;62cv=N5?89?p1td&(ePiD(V0NS* zO*(zL%3#3V}XbY_9LzY=v_f-Mest!t!5Q{N#;;UzPG%T2IDLNrt@e z<4dlf&(VJARv4OL~Ox;7v<6|2|2|`Xp%@%$XLJZ4oIS1RI4* z{=Z2U;sJQXlf8&oL4B7^)Os|?u$9~qS7`>+^N}KFic}R$*t349P=;l2OCZ~&SB(It zuj^J=7uy3A%uw=Pku-9WorPjpt&3^h0Sjzx0X^S?8*Wn4BgGx#Z#DgkB0Z8p!Jf{_fi#pE?IuOn2q34eHCeSPtz8C3|V0G ziBtJnrD0!kmwJcNOF0@Cmt>K_thTG5ac34c*!nyoccv?hB<14Q-L55-uAtB)tTRUZn3le3$d*qt%|UBdf!9d*D_5X(s9^*tM1O55&LB z_4qC#30XaO=8iksJ=Slj+J&=}cL(SXXLN6-k*+q#K63#U{n%|? zJPV!oRBtiTxbLx^1g71PmDE!hS^q#IH{HdO5+=$!H9+5-whHKMD?{>Hp3ScT!zOGg zM-uoRY5+mvuIK@db;hlP=Mjt!Vrbsk(0v)8r7jGYB(oJ33Q&K{{&ourpQSzZ<&*3Q#h&X2t`v%sHmu~7ua3WgTbs}ECp$4gg{JX)Oje=RF9v97lGn^8^#B&7K=O9 z*N*ZUpJNP(;)rJweC78%%+G!RN(nv}I(K0GszV~=EHW*b$$W$#5`e4T^o+O#ob=$T z+gkl4#%)?rhgVfM8wMNcmugvt@K+97P#H#vk9W1pT9+ z5|6F%YX3r|C7KOKQ|uQzJho3=w?0>JYdCqg@r1w9ERcwz?>=dAtx20A`5hFeQ0iKT zs@bU#*_--;(8$D3=5-R-VHasvkLNR!y9MxKzDlXEP#fv`Dc|j?k`zZF?v2e5VFv{m zhhrPU={%N)c)2+z(a=*sj0dD`7RXJ4pO+lSxzALIBx5+Svf#OPV-`r-)#VEn)0FMj zt+H$+_FOZND`;oYBhv_q7cDZdra!ilGYJFBk6q{9XtV&|;n=L_+VtAdD-B~y18bFJ zFx*XAUNTu7F=_7YpD$AB6~h~t7g&=G*f}O3<&3mZ%C;F;7b0&FbjYGFMzlrlCAtAQ zbES&__cR++l48{Chi@G_IG(DeGzmx{f*>s>I-gh|n;95WBld^|xQ;fMJC3y;K)@y- zh`L~SgPu14apf2k=GPsmy;FhA7DtVzZ^n`9#69v<4OzC}&Z@cpiSgYD-ZPCq4Ip<3 zC$H#fPKe}xw6tdwu{yabTN`K%RznZ9F8$)D?_!;WaEEUs>br6X96D&9(stMcEZ>HW z>O7ZUd+u^dLJuUE>uar6*bk~8OjTg55)`Y=imOA4@dz$S+wdA9ZLCoY7%B&MJ<(PG z*F!DbUiCZMBC=1OsopuzaKRzZv0a(&K6tVAHYY0%l!K?o=q28zd!-YZST*UK1ktqi%kf(kk@11Y81XleHh+ zEf5-6Jsb}q9)VG^j-&Tru%7jt_-y8a;uQgFP?C8m5uwltHW;~IFc(Q-Y2Lh+V!?!% zfd>-=Ra9Fq5LmxMO&DdXIUjZ7t+*w>6ei%Kzd4=zOm#3zPviHeS8s_JatfEFZK^(D zx%I+k8s=|FP=FWu_{wG#-04OGCd<5s*G471Ti+viA=tBtm70ppC+d-4o6jnTrR;Ebu=dX+Hv z4cur1otoI53_{}u)+=5ychZ5+m@&U8GobSjgp%*5-l>}tS=Hb~iYVB<_9J&KepzlMhpFhaUgT~_ zn8sqjkKuCRg;s~STFNHQVX(Jb32KQ>qQ~8!xgud#Tr@Ti(!Qlxm{GlIvNB;1)pZxL z;RuP4LSO-em>?lCvOu8eW9%vv} zW=q>{wZd8y3$k@x&Uqi3Zg>moP@Ns2B4e6rMubAr)fv6kN17F+-LuX<{Flp)wd(cS z99h+Cx%~qwPIsE4oRZMpG~1(k#qU0wi!tIy3XiLp*C9Z5c>FkSD@mc_o##@qr({h4 zldfN2xm=CH{JU6=Jlu45xCYT;Lx8->0{ANG=!;GYE}iMq4~@7v@)E2kc^_^; z*ETug7q}9*816d)Y-Szt>Nl;<=2Y8Hccv~odND;Y2Zkv{)zgn=f9o(nkH*0f+8sC0 zIlE3&H$OaLVXRgQF`s>olH%e^a>(p9RVylzW4!0CJl6vEz@mRCNUNh18}!qWU*_FM z>=KdeJS4NM1iKf)u5&r;n*iqTPK3swL3`~1WJ0E%m)#{Mz7WMh|DjDJw>(l_%%I3l z%lK0Y&&{|S-ho1qx;M4;sLvxfHou(rul+zTm*`;?UBBVYN ziP;)AVna@LH>-Q~V2r>O5yRMXUO;AUsxd9Mz^Q3TYWPhVX{{%2!&itWv4C`l2J<4F z^R(uLYW-3oDm9fZ&$b83_r~~SmF7PlHEG!F{}X8YP)*4V7z#og!faOf?2#f2a*OZv zUak7bbG=>J1Am+21hdP;lk{d}4X7T*V~q?Dgg)r-Lx)}ou+;>&V$RnGUh_b``m7*r z#7X518)OG^K(^>Bxi$(#MLsG?sm>2w{ER^)$>Cm*(lvv-t69#AiOlu{zcr{B7@%UX z@wyXq9y5W+XS>d)Y+ME&<$iFY&vXR??G})Pp;6Xle|pXi1Tqw3z+&1A_GZIbc#Pab z9&)Hgngk1MyQEhT1j38~tcdSbr;y;6c=*K7Bivk38bmZzZGmx_l?S=Wga%7f$byV% zTMly=n<1v!hbtGcFpf%wYGYA?K5xSZaQ)`5&3-wSgO!I++6M79m|1_FxGClXRw<}z z((izREO&pMFv?u!i=%Sf8gzorn}T_4e^dL*x_bu!Z0UIU_6mBzZ-3}irm8+cXMW{R|E0utk_H>5Nvm7%(`TRZ z+T(OEM%^BrN4@@G6xOk~CL~$n801?}y!rYU!#Up$&Vf$H>;FDTxN`roGijAb%%J6x z{{1RYoUdB3%M%7w6Wu-RNiq6Qjf`YT1peY1qpWFvzOYo@FR&PK`~=PI?SEbvN-q^@ zCPa8v4{+Z7#}9ph<-aFJeZBl=Gk8&b$*=k)LvU z!*A;kt-Fj6a2ylscn@vc@2^$zgH^=xOVVyIbN&6b55-_%zR Date: Wed, 17 Jan 2024 17:32:09 +0800 Subject: [PATCH 4/4] =?UTF-8?q?[ptdbg=5Fascend]=E7=B2=BE=E5=BA=A6=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E8=B5=84=E6=96=99=E4=B8=BB=E6=8E=A8debugger=E6=95=B4?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...7\345\212\237\350\203\275\350\257\264\346\230\216_v4.0.md" | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git "a/debug/accuracy_tools/ptdbg_ascend/doc/ptdbg_ascend\347\262\276\345\272\246\345\267\245\345\205\267\345\212\237\350\203\275\350\257\264\346\230\216_v4.0.md" "b/debug/accuracy_tools/ptdbg_ascend/doc/ptdbg_ascend\347\262\276\345\272\246\345\267\245\345\205\267\345\212\237\350\203\275\350\257\264\346\230\216_v4.0.md" index 089872449d..1914803364 100644 --- "a/debug/accuracy_tools/ptdbg_ascend/doc/ptdbg_ascend\347\262\276\345\272\246\345\267\245\345\205\267\345\212\237\350\203\275\350\257\264\346\230\216_v4.0.md" +++ "b/debug/accuracy_tools/ptdbg_ascend/doc/ptdbg_ascend\347\262\276\345\272\246\345\267\245\345\205\267\345\212\237\350\203\275\350\257\264\346\230\216_v4.0.md" @@ -213,7 +213,7 @@ PyTorch训练场景的精度问题分析建议参考以下思路进行精度比 3. NPU环境下执行训练dump溢出数据。 - 针对输入正常但输出存在溢出的API,会训练执行目录下将溢出的API信息dump并保存为`forward_info_{pid}.json`和`backward_info_{pid}.json`,通过 [Ascend模型精度预检工具](https://gitee.com/ascend/att/tree/master/debug/accuracy_tools/api_accuracy_checker)对json文件进行解析,输出溢出API为正常溢出还是非正常溢出,从而帮助用户快速判断。 + 针对输入正常但输出存在溢出的API,会训练执行目录下将溢出的API信息dump并保存为`forward_info_{pid}.json`和`backward_info_{pid}.json`,通过[Ascend模型精度预检工具](https://gitee.com/ascend/att/tree/master/debug/accuracy_tools/api_accuracy_checker)对json文件进行解析,输出溢出API为正常溢出还是非正常溢出,从而帮助用户快速判断。 精度预检工具执行命令如下: @@ -662,7 +662,7 @@ PrecisionDebugger(dump_path=None, hook_name=None, rank=None, step=[], enable_dat | dump_path | 设置dump数据目录路径,参数示例:"./dump_path"。
默认在dump_path目录下生成`ptdbg_dump_{version}`目录,并在该目录下生成`dump.pkl`文件以及`dump`数据文件保存目录。
当**configure_hook**函数配置了mode参数时,`dump.pkl`文件以及`dump`数据文件保存目录名称添加mode参数值为前缀,详情请参见“**dump数据存盘说明**”。
未配置dump_path时,也可以通过环境变量ASCEND_WORK_PATH配置dump路径,此时dump数据将落盘在${ASCEND_WORK_PATH}/dump_data下,自定义配置dump_path优先级高于环境变量,dump_path和环境变量需要二选一。 | 否 | | hook_name | dump模式,可取值dump和overflow_check,表示dump和溢出检测功能,二选一。 | 是 | | rank | 指定对某张卡上的数据进行dump或溢出检测,默认未配置(表示dump所有卡的数据),须根据实际卡的Rank ID配置。应配置为大于0的正整数,且须根据实际卡的Rank ID配置,若所配置的值大于实际训练所运行的卡的Rank ID,则dump数据为空,比如当前环境Rank ID为0~7,实际训练运行0~3卡,此时若配置Rank ID为4或不存在的10等其他值,此时dump数据为空。 | 否 | -| step | 指定dump某个step的数据,默认未配置,须指定为训练脚本中存在的step。step为list格式,可配置逐个step,例如:step=[0,1,2];也可以配置step范围,例如:step=list(range(0,9)),表示dump第0到第8个step。 | 否 | +| step | 指定dump某个step的数据,默认未配置,表示dump所有step数据。dump特定step时,须指定为训练脚本中存在的step。step为list格式,可配置逐个step,例如:step=[0,1,2];也可以配置step范围,例如:step=list(range(0,9)),表示dump第0到第8个step。 | 否 | | enable_dataloader | 自动控制开关,可取值True(开启)或False(关闭),默认为False。配置为True后自动识别dump step参数指定的迭代,并在该迭代执行完成后退出训练,此时start和stop函数可不配置,开启该开关要求训练脚本是通过torch.utils.data.dataloader方式加载数据;配置为False则需要配置start和stop函数,并在最后一个stop函数后或一个step结束的位置添加debugger.step()。 | 否 | | model | 开启model模式,传入网络模型实例化的对象,配置该参数后,dump操作仅dump网络中init方法里调用的方法(nn.Module类),不会对所有API进行dump。参数示例: model=net,net为网络模型实例化的对象名称。默认未配置。
配置该参数时,PrecisionDebugger模块请在模型实例化之后调用。
该模式不支持“溢出检测”和“模块级精度数据dump”。 | 否 | -- Gitee