mindstudio-probe 1.0.3__py3-none-any.whl → 1.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mindstudio_probe-1.0.3.dist-info → mindstudio_probe-1.1.0.dist-info}/LICENSE +201 -201
- {mindstudio_probe-1.0.3.dist-info → mindstudio_probe-1.1.0.dist-info}/METADATA +36 -34
- mindstudio_probe-1.1.0.dist-info/RECORD +287 -0
- {mindstudio_probe-1.0.3.dist-info → mindstudio_probe-1.1.0.dist-info}/WHEEL +1 -1
- {mindstudio_probe-1.0.3.dist-info → mindstudio_probe-1.1.0.dist-info}/entry_points.txt +1 -0
- msprobe/README.md +131 -237
- msprobe/__init__.py +16 -1
- msprobe/{config/config.json → config.json} +47 -49
- msprobe/core/advisor/advisor.py +124 -124
- msprobe/core/advisor/advisor_const.py +58 -59
- msprobe/core/advisor/advisor_result.py +58 -58
- msprobe/core/common/const.py +402 -318
- msprobe/core/common/exceptions.py +99 -99
- msprobe/core/common/{file_check.py → file_utils.py} +523 -283
- msprobe/core/common/inplace_op_checker.py +38 -0
- msprobe/core/common/inplace_ops.yaml +251 -0
- msprobe/core/common/log.py +86 -69
- msprobe/core/common/utils.py +371 -616
- msprobe/core/common_config.py +78 -71
- msprobe/core/compare/acc_compare.py +472 -298
- msprobe/core/compare/check.py +180 -95
- msprobe/core/compare/compare_cli.py +69 -49
- msprobe/core/compare/highlight.py +259 -222
- msprobe/core/compare/multiprocessing_compute.py +174 -149
- msprobe/core/compare/npy_compare.py +310 -295
- msprobe/core/compare/utils.py +464 -429
- msprobe/core/data_dump/data_collector.py +153 -144
- msprobe/core/data_dump/data_processor/base.py +337 -293
- msprobe/core/data_dump/data_processor/factory.py +76 -59
- msprobe/core/data_dump/data_processor/mindspore_processor.py +192 -198
- msprobe/core/data_dump/data_processor/pytorch_processor.py +383 -389
- msprobe/core/data_dump/json_writer.py +117 -116
- msprobe/core/data_dump/scope.py +194 -178
- msprobe/core/grad_probe/constant.py +74 -70
- msprobe/core/grad_probe/grad_compare.py +170 -175
- msprobe/core/grad_probe/utils.py +77 -52
- msprobe/docs/01.installation.md +99 -0
- msprobe/docs/02.config_introduction.md +137 -0
- msprobe/docs/03.config_examples.md +237 -0
- msprobe/docs/04.acl_config_examples.md +78 -0
- msprobe/docs/05.data_dump_PyTorch.md +326 -0
- msprobe/docs/06.data_dump_MindSpore.md +285 -0
- msprobe/docs/07.accuracy_checker_PyTorch.md +297 -0
- msprobe/docs/08.accuracy_checker_online_PyTorch.md +238 -0
- msprobe/docs/09.accuracy_checker_MindSpore.md +68 -0
- msprobe/docs/10.accuracy_compare_PyTorch.md +327 -0
- msprobe/docs/11.accuracy_compare_MindSpore.md +333 -0
- msprobe/docs/12.overflow_check_PyTorch.md +79 -0
- msprobe/docs/13.overflow_check_MindSpore.md +31 -0
- msprobe/{pytorch/doc/parse_tool.md → docs/14.data_parse_PyTorch.md} +283 -286
- msprobe/docs/15.free_benchmarking_PyTorch.md +170 -0
- msprobe/docs/16.free_benchmarking_MindSpore.md +140 -0
- msprobe/{doc/grad_probe/grad_probe.md → docs/17.grad_probe.md} +205 -207
- msprobe/{pytorch/doc//321/205/320/254/320/270/321/207/342/225/221/342/224/220/321/207/342/226/223/342/225/233/321/205/342/225/221/320/266/321/206/320/277/320/244/321/205/320/277/342/225/243.md → docs/18.online_dispatch.md} +89 -90
- msprobe/docs/FAQ.md +189 -0
- msprobe/docs/S02.report_free_benchmarking_validation_performance_baseline.md +146 -0
- msprobe/docs/img/free_benchmark_framework.png +0 -0
- msprobe/docs/img/ms_dump.png +0 -0
- msprobe/docs/img/ms_layer.png +0 -0
- msprobe/docs/img/pt_dump.png +0 -0
- msprobe/mindspore/__init__.py +2 -1
- msprobe/mindspore/api_accuracy_checker/api_accuracy_checker.py +278 -245
- msprobe/mindspore/api_accuracy_checker/api_info.py +76 -69
- msprobe/mindspore/api_accuracy_checker/api_runner.py +155 -151
- msprobe/mindspore/api_accuracy_checker/base_compare_algorithm.py +196 -196
- msprobe/mindspore/api_accuracy_checker/cmd_parser.py +6 -0
- msprobe/mindspore/api_accuracy_checker/compute_element.py +238 -223
- msprobe/mindspore/api_accuracy_checker/main.py +8 -15
- msprobe/mindspore/api_accuracy_checker/type_mapping.py +113 -113
- msprobe/mindspore/api_accuracy_checker/utils.py +79 -62
- msprobe/mindspore/cell_processor.py +58 -34
- msprobe/mindspore/common/const.py +108 -87
- msprobe/mindspore/common/log.py +37 -37
- msprobe/mindspore/common/utils.py +97 -57
- msprobe/mindspore/compare/distributed_compare.py +62 -75
- msprobe/mindspore/compare/layer_mapping.py +146 -0
- msprobe/mindspore/compare/modify_mapping.py +107 -0
- msprobe/mindspore/compare/ms_compare.py +357 -117
- msprobe/mindspore/compare/ms_graph_compare.py +364 -317
- msprobe/mindspore/compare/ms_to_pt_api.yaml +399 -399
- msprobe/mindspore/debugger/debugger_config.py +69 -74
- msprobe/mindspore/debugger/precision_debugger.py +150 -107
- msprobe/mindspore/dump/dump_tool_factory.py +50 -35
- msprobe/mindspore/dump/hook_cell/api_registry.py +128 -104
- msprobe/mindspore/dump/hook_cell/hook_cell.py +55 -53
- msprobe/mindspore/dump/hook_cell/primitive_hooks.py +206 -0
- msprobe/mindspore/dump/hook_cell/support_wrap_ops.yaml +994 -925
- msprobe/mindspore/dump/hook_cell/wrap_api.py +121 -0
- msprobe/mindspore/dump/jit_dump.py +96 -56
- msprobe/mindspore/dump/kernel_graph_dump.py +75 -60
- msprobe/mindspore/dump/kernel_kbyk_dump.py +79 -65
- msprobe/mindspore/free_benchmark/api_pynative_self_check.py +131 -116
- msprobe/mindspore/free_benchmark/common/config.py +27 -12
- msprobe/mindspore/free_benchmark/common/handler_params.py +32 -17
- msprobe/mindspore/free_benchmark/common/utils.py +85 -71
- msprobe/mindspore/free_benchmark/data/support_wrap_ops.yaml +842 -842
- msprobe/mindspore/free_benchmark/decorator/dec_forward.py +57 -42
- msprobe/mindspore/free_benchmark/decorator/decorator_factory.py +122 -107
- msprobe/mindspore/free_benchmark/handler/base_handler.py +105 -90
- msprobe/mindspore/free_benchmark/handler/check_handler.py +56 -41
- msprobe/mindspore/free_benchmark/handler/fix_handler.py +51 -36
- msprobe/mindspore/free_benchmark/handler/handler_factory.py +36 -21
- msprobe/mindspore/free_benchmark/perturbation/add_noise.py +82 -67
- msprobe/mindspore/free_benchmark/perturbation/base_perturbation.py +36 -21
- msprobe/mindspore/free_benchmark/perturbation/bit_noise.py +78 -63
- msprobe/mindspore/free_benchmark/perturbation/exchange_value.py +77 -0
- msprobe/mindspore/free_benchmark/perturbation/improve_precision.py +49 -34
- msprobe/mindspore/free_benchmark/perturbation/no_change.py +27 -12
- msprobe/mindspore/free_benchmark/perturbation/perturbation_factory.py +44 -27
- msprobe/mindspore/free_benchmark/self_check_tool_factory.py +48 -33
- msprobe/mindspore/grad_probe/global_context.py +100 -91
- msprobe/mindspore/grad_probe/grad_analyzer.py +231 -231
- msprobe/mindspore/grad_probe/grad_monitor.py +27 -27
- msprobe/mindspore/grad_probe/grad_stat_csv.py +131 -131
- msprobe/mindspore/grad_probe/hook.py +94 -92
- msprobe/mindspore/grad_probe/utils.py +29 -28
- msprobe/mindspore/ms_config.py +128 -126
- msprobe/mindspore/overflow_check/kernel_graph_overflow_check.py +60 -45
- msprobe/mindspore/overflow_check/overflow_check_tool_factory.py +49 -34
- msprobe/mindspore/runtime.py +4 -4
- msprobe/mindspore/service.py +297 -354
- msprobe/mindspore/task_handler_factory.py +24 -24
- msprobe/msprobe.py +105 -107
- msprobe/pytorch/__init__.py +23 -4
- msprobe/pytorch/api_accuracy_checker/common/config.py +70 -55
- msprobe/pytorch/api_accuracy_checker/common/utils.py +246 -165
- msprobe/pytorch/api_accuracy_checker/compare/algorithm.py +230 -213
- msprobe/pytorch/api_accuracy_checker/compare/api_precision_compare.py +632 -581
- msprobe/pytorch/api_accuracy_checker/compare/api_precision_standard.yaml +132 -132
- msprobe/pytorch/api_accuracy_checker/compare/api_precision_threshold.yaml +390 -390
- msprobe/pytorch/api_accuracy_checker/compare/compare.py +416 -381
- msprobe/pytorch/api_accuracy_checker/compare/compare_column.py +90 -73
- msprobe/pytorch/api_accuracy_checker/compare/compare_utils.py +265 -244
- msprobe/pytorch/api_accuracy_checker/config.yaml +10 -10
- msprobe/pytorch/api_accuracy_checker/run_ut/data_generate.py +370 -332
- msprobe/pytorch/api_accuracy_checker/run_ut/multi_run_ut.py +221 -199
- msprobe/pytorch/api_accuracy_checker/run_ut/run_overflow_check.py +150 -134
- msprobe/pytorch/api_accuracy_checker/run_ut/run_ut.py +518 -581
- msprobe/pytorch/api_accuracy_checker/run_ut/run_ut_utils.py +213 -74
- msprobe/pytorch/api_accuracy_checker/run_ut/torch_ut_setting.json +7 -4
- msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/attl.py +218 -202
- msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/client.py +370 -324
- msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/device_dispatch.py +227 -204
- msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/dump_dispatch.py +110 -0
- msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/server.py +244 -218
- msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/torch_ops_config.yaml +63 -0
- msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/utils.py +44 -0
- msprobe/pytorch/bench_functions/__init__.py +30 -15
- msprobe/pytorch/bench_functions/apply_adam_w.py +43 -28
- msprobe/pytorch/bench_functions/confusion_transpose.py +34 -19
- msprobe/pytorch/bench_functions/fast_gelu.py +70 -55
- msprobe/pytorch/bench_functions/layer_norm_eval.py +21 -6
- msprobe/pytorch/bench_functions/linear.py +27 -12
- msprobe/pytorch/bench_functions/matmul_backward.py +63 -48
- msprobe/pytorch/bench_functions/npu_fusion_attention.py +538 -421
- msprobe/pytorch/bench_functions/rms_norm.py +30 -15
- msprobe/pytorch/bench_functions/rotary_mul.py +71 -52
- msprobe/pytorch/bench_functions/scaled_mask_softmax.py +41 -26
- msprobe/pytorch/bench_functions/swiglu.py +70 -55
- msprobe/pytorch/common/__init__.py +17 -2
- msprobe/pytorch/common/compare_script.template +14 -14
- msprobe/pytorch/common/log.py +33 -32
- msprobe/pytorch/common/parse_json.py +54 -39
- msprobe/pytorch/common/utils.py +310 -300
- msprobe/pytorch/compare/distributed_compare.py +66 -66
- msprobe/pytorch/compare/mapping.yaml +607 -607
- msprobe/pytorch/compare/match.py +49 -33
- msprobe/pytorch/compare/pt_compare.py +82 -40
- msprobe/pytorch/debugger/debugger_config.py +108 -95
- msprobe/pytorch/debugger/precision_debugger.py +173 -125
- msprobe/pytorch/free_benchmark/__init__.py +23 -8
- msprobe/pytorch/free_benchmark/common/constant.py +70 -70
- msprobe/pytorch/free_benchmark/common/counter.py +71 -71
- msprobe/pytorch/free_benchmark/common/enums.py +65 -37
- msprobe/pytorch/free_benchmark/common/params.py +144 -129
- msprobe/pytorch/free_benchmark/common/utils.py +118 -102
- msprobe/pytorch/free_benchmark/compare/grad_saver.py +200 -179
- msprobe/pytorch/free_benchmark/compare/single_benchmark.py +119 -104
- msprobe/pytorch/free_benchmark/main.py +120 -105
- msprobe/pytorch/free_benchmark/perturbed_layers/base_layer.py +28 -13
- msprobe/pytorch/free_benchmark/perturbed_layers/layer_factory.py +56 -41
- msprobe/pytorch/free_benchmark/perturbed_layers/npu/add_noise.py +105 -90
- msprobe/pytorch/free_benchmark/perturbed_layers/npu/bit_noise.py +119 -104
- msprobe/pytorch/free_benchmark/perturbed_layers/npu/change_value.py +87 -63
- msprobe/pytorch/free_benchmark/perturbed_layers/npu/improve_precision.py +83 -68
- msprobe/pytorch/free_benchmark/perturbed_layers/npu/no_change.py +43 -28
- msprobe/pytorch/free_benchmark/perturbed_layers/npu/npu_base_layser.py +60 -45
- msprobe/pytorch/free_benchmark/perturbed_layers/run_cpu.py +34 -19
- msprobe/pytorch/free_benchmark/result_handlers/base_handler.py +256 -217
- msprobe/pytorch/free_benchmark/result_handlers/check_handler.py +54 -39
- msprobe/pytorch/free_benchmark/result_handlers/fix_handler.py +38 -23
- msprobe/pytorch/free_benchmark/result_handlers/handler_factory.py +45 -30
- msprobe/pytorch/free_benchmark/result_handlers/preheat_handler.py +185 -170
- msprobe/pytorch/function_factory.py +91 -75
- msprobe/pytorch/functional/module_dump.py +84 -0
- msprobe/pytorch/grad_probe/grad_monitor.py +91 -90
- msprobe/pytorch/grad_probe/grad_stat_csv.py +128 -128
- msprobe/pytorch/hook_module/__init__.py +16 -1
- msprobe/pytorch/hook_module/api_registry.py +166 -161
- msprobe/pytorch/hook_module/hook_module.py +118 -120
- msprobe/pytorch/hook_module/support_wrap_ops.yaml +1879 -1877
- msprobe/pytorch/hook_module/utils.py +28 -29
- msprobe/pytorch/hook_module/wrap_aten.py +111 -110
- msprobe/pytorch/hook_module/wrap_distributed.py +77 -78
- msprobe/pytorch/hook_module/wrap_functional.py +104 -105
- msprobe/pytorch/hook_module/wrap_npu_custom.py +85 -84
- msprobe/pytorch/hook_module/wrap_tensor.py +69 -71
- msprobe/pytorch/hook_module/wrap_torch.py +84 -86
- msprobe/pytorch/hook_module/wrap_vf.py +60 -62
- msprobe/pytorch/module_processer.py +153 -138
- msprobe/pytorch/online_dispatch/__init__.py +20 -20
- msprobe/pytorch/online_dispatch/compare.py +235 -236
- msprobe/pytorch/online_dispatch/dispatch.py +271 -271
- msprobe/pytorch/online_dispatch/dump_compare.py +155 -156
- msprobe/pytorch/online_dispatch/single_compare.py +391 -391
- msprobe/pytorch/online_dispatch/torch_ops_config.yaml +57 -49
- msprobe/pytorch/online_dispatch/utils.py +127 -146
- msprobe/pytorch/parse.py +19 -4
- msprobe/pytorch/parse_tool/cli.py +31 -32
- msprobe/pytorch/parse_tool/lib/compare.py +259 -271
- msprobe/pytorch/parse_tool/lib/config.py +52 -52
- msprobe/pytorch/parse_tool/lib/file_desc.py +31 -31
- msprobe/pytorch/parse_tool/lib/interactive_cli.py +102 -102
- msprobe/pytorch/parse_tool/lib/parse_exception.py +54 -54
- msprobe/pytorch/parse_tool/lib/parse_tool.py +161 -158
- msprobe/pytorch/parse_tool/lib/utils.py +320 -321
- msprobe/pytorch/parse_tool/lib/visualization.py +85 -91
- msprobe/pytorch/pt_config.py +317 -187
- msprobe/pytorch/service.py +311 -252
- mindstudio_probe-1.0.3.dist-info/RECORD +0 -272
- msprobe/config/README.md +0 -539
- msprobe/mindspore/doc/compare.md +0 -58
- msprobe/mindspore/doc/dump.md +0 -217
- msprobe/mindspore/dump/hook_cell/wrap_functional.py +0 -91
- msprobe/mindspore/dump/hook_cell/wrap_tensor.py +0 -63
- msprobe/pytorch/api_accuracy_checker/tensor_transport_layer/ssl_config.py +0 -10
- msprobe/pytorch/doc/FAQ.md +0 -193
- msprobe/pytorch/doc/api_accuracy_checker.md +0 -313
- msprobe/pytorch/doc/api_accuracy_checker_online.md +0 -187
- msprobe/pytorch/doc/dump.md +0 -260
- msprobe/pytorch/doc/msprobe/321/207/342/226/223/342/225/233/321/205/342/225/221/320/266/321/205/342/225/226/320/265/321/205/320/225/342/225/226/321/206/320/245/342/226/221/321/206/320/235/320/276dump/321/206/320/260/320/227/321/205/320/227/320/226/321/206/320/220/320/267/321/210/320/223/342/225/234/321/205/320/257/342/225/221/321/207/342/225/221/342/224/220/321/206/320/232/320/265/321/205/320/241/320/232.md +0 -182
- msprobe/pytorch/doc/ptdbg_ascend_compare.md +0 -240
- msprobe/pytorch/doc/ptdbg_ascend_overview.md +0 -68
- msprobe/pytorch/doc/ptdbg_ascend_quickstart.md +0 -381
- msprobe/pytorch/doc/run_overflow_check.md +0 -25
- msprobe/pytorch/doc//321/206/320/247/320/260/321/206/320/260/320/227/321/206/320/255/320/226/321/205/342/225/226/320/265/321/205/320/225/342/225/226/321/205/320/254/342/225/221/321/206/320/251/320/277/321/211/320/272/320/234/321/210/320/277/320/221/321/205/320/242/320/234/321/206/320/220/320/267/321/210/320/223/342/225/234/321/205/320/257/342/225/221/321/207/342/225/221/342/224/220/321/206/320/232/320/265/321/205/320/241/320/232.md +0 -151
- msprobe/pytorch/functional/data_processor.py +0 -0
- msprobe/pytorch/functional/dump_module.py +0 -39
- {mindstudio_probe-1.0.3.dist-info → mindstudio_probe-1.1.0.dist-info}/top_level.txt +0 -0
- /msprobe/{pytorch/doc → docs}/img/BLOOM-7B_1.png +0 -0
- /msprobe/{pytorch/doc → docs}/img/BLOOM-7B_2.png +0 -0
- /msprobe/{pytorch/doc → docs}/img/BLOOM-7B_3.png +0 -0
- /msprobe/{pytorch/doc → docs}/img/BLOOM-7B_4.png +0 -0
- /msprobe/{pytorch/doc → docs}/img/GPT-3_1.png +0 -0
- /msprobe/{pytorch/doc → docs}/img/GPT-3_2.png +0 -0
- /msprobe/{pytorch/doc → docs}/img/GPT-3_3.png +0 -0
- /msprobe/{pytorch/doc → docs}/img/GPT-3_4.png +0 -0
- /msprobe/{pytorch/doc → docs}/img/GPT-3_5.png +0 -0
- /msprobe/{pytorch/doc → docs}/img/GPT-3_6.png +0 -0
- /msprobe/{pytorch/doc → docs}/img/GPT-3_7.png +0 -0
- /msprobe/{pytorch/doc → docs}/img/GPT-3_8.png +0 -0
- /msprobe/{pytorch/doc → docs}/img/YOLOV5S_1.png +0 -0
- /msprobe/{pytorch/doc → docs}/img/YOLOV5S_2.png +0 -0
- /msprobe/{pytorch/doc → docs}/img/accuracy_checking_details.png +0 -0
- /msprobe/{pytorch/doc → docs}/img/accuracy_checking_result.png +0 -0
- /msprobe/{pytorch/doc → docs}/img/api_precision_compare_details.png +0 -0
- /msprobe/{pytorch/doc → docs}/img/api_precision_compare_result.png +0 -0
- /msprobe/{pytorch/doc → docs}/img/auto_analyze_log.png +0 -0
- /msprobe/{pytorch/doc → docs}/img/compare_result_pkl.png +0 -0
- /msprobe/{pytorch/doc → docs}/img/compare_result_pkl_md5.png.png +0 -0
- /msprobe/{pytorch/doc → docs}/img/cpu_info.png +0 -0
- /msprobe/{config → docs}/img/free_benchmark.png +0 -0
- /msprobe/{doc/grad_probe/img/image-1.png → docs/img/grad_probe_image-1.png} +0 -0
- /msprobe/{doc/grad_probe/img/image-2.png → docs/img/grad_probe_image-2.png} +0 -0
- /msprobe/{doc/grad_probe/img/image-3.png → docs/img/grad_probe_image-3.png} +0 -0
- /msprobe/{doc/grad_probe/img/image-4.png → docs/img/grad_probe_image-4.png} +0 -0
- /msprobe/{doc/grad_probe/img/image.png → docs/img/grad_probe_image.png} +0 -0
- /msprobe/{pytorch/doc → docs}/img/module_compare.png +0 -0
|
@@ -1,71 +1,75 @@
|
|
|
1
|
-
|
|
2
|
-
class GradConst:
|
|
3
|
-
|
|
4
|
-
FRAMEWORKS = {"PyTorch", "MindSpore"}
|
|
5
|
-
PYTORCH = "PyTorch"
|
|
6
|
-
MindSpore = "MindSpore"
|
|
7
|
-
|
|
8
|
-
GRAD_FILE_SUFFIX = {"npy", "pt"}
|
|
9
|
-
NPY_SUFFIX = "npy"
|
|
10
|
-
PT_SUFFIX = "pt"
|
|
11
|
-
|
|
12
|
-
# for callback
|
|
13
|
-
CURRENT_STEP = "current_step"
|
|
14
|
-
|
|
15
|
-
PARAM_LIST = "param_list"
|
|
16
|
-
RANK = "rank"
|
|
17
|
-
STEP = "step"
|
|
18
|
-
BOUNDS = "bounds"
|
|
19
|
-
OUTPUT_PATH = "output_path"
|
|
20
|
-
|
|
21
|
-
# level const
|
|
22
|
-
LEVEL = "level"
|
|
23
|
-
LEVEL0 = "L0"
|
|
24
|
-
LEVEL1 = "L1"
|
|
25
|
-
LEVEL2 = "L2"
|
|
26
|
-
SUPPORTED_LEVEL = {"L0", "L1", "L2"}
|
|
27
|
-
|
|
28
|
-
# numpy coding
|
|
29
|
-
STEP_IDX = 0
|
|
30
|
-
SHAPE_DIM_IDX = 4
|
|
31
|
-
MAX_SIZE = 10 * 1024 * 1024 * 1024
|
|
32
|
-
|
|
33
|
-
# direction suffix
|
|
34
|
-
DIR_SUFFIX = "dir.npy"
|
|
35
|
-
|
|
36
|
-
#
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
"
|
|
64
|
-
"header": [GradConst.MAX, GradConst.MIN, GradConst.NORM, GradConst.SHAPE],
|
|
65
|
-
"have_grad_direction":
|
|
66
|
-
},
|
|
67
|
-
"
|
|
68
|
-
"header": [GradConst.
|
|
69
|
-
"have_grad_direction": True
|
|
70
|
-
},
|
|
1
|
+
|
|
2
|
+
class GradConst:
|
|
3
|
+
|
|
4
|
+
FRAMEWORKS = {"PyTorch", "MindSpore"}
|
|
5
|
+
PYTORCH = "PyTorch"
|
|
6
|
+
MindSpore = "MindSpore"
|
|
7
|
+
|
|
8
|
+
GRAD_FILE_SUFFIX = {"npy", "pt"}
|
|
9
|
+
NPY_SUFFIX = "npy"
|
|
10
|
+
PT_SUFFIX = "pt"
|
|
11
|
+
|
|
12
|
+
# for callback
|
|
13
|
+
CURRENT_STEP = "current_step"
|
|
14
|
+
|
|
15
|
+
PARAM_LIST = "param_list"
|
|
16
|
+
RANK = "rank"
|
|
17
|
+
STEP = "step"
|
|
18
|
+
BOUNDS = "bounds"
|
|
19
|
+
OUTPUT_PATH = "output_path"
|
|
20
|
+
|
|
21
|
+
# level const
|
|
22
|
+
LEVEL = "level"
|
|
23
|
+
LEVEL0 = "L0"
|
|
24
|
+
LEVEL1 = "L1"
|
|
25
|
+
LEVEL2 = "L2"
|
|
26
|
+
SUPPORTED_LEVEL = {"L0", "L1", "L2"}
|
|
27
|
+
|
|
28
|
+
# numpy coding
|
|
29
|
+
STEP_IDX = 0
|
|
30
|
+
SHAPE_DIM_IDX = 4
|
|
31
|
+
MAX_SIZE = 10 * 1024 * 1024 * 1024
|
|
32
|
+
|
|
33
|
+
# direction suffix
|
|
34
|
+
DIR_SUFFIX = "dir.npy"
|
|
35
|
+
|
|
36
|
+
# bounds safety
|
|
37
|
+
BOUNDS_MINIMUM = -2**63
|
|
38
|
+
BOUNDS_MAXIMUM = 2**63 - 1
|
|
39
|
+
|
|
40
|
+
# file safty
|
|
41
|
+
DATA_DIR_AUTHORITY = 0o750
|
|
42
|
+
DATA_FILE_AUTHORITY = 0o640
|
|
43
|
+
DIRECTORY_LENGTH = 4096
|
|
44
|
+
FILE_NAME_LENGTH = 255
|
|
45
|
+
FILE_VALID_PATTERN = r"^[a-zA-Z0-9_.:/-]+$"
|
|
46
|
+
PARAM_VALID_PATTERN = r"^[a-zA-Z0-9_.]+$"
|
|
47
|
+
DIR = "dir"
|
|
48
|
+
FILE = "file"
|
|
49
|
+
|
|
50
|
+
STEP_FINISH = "step_finish"
|
|
51
|
+
|
|
52
|
+
SUMMARY = "summary"
|
|
53
|
+
|
|
54
|
+
# csv header entry
|
|
55
|
+
MD5 = "MD5"
|
|
56
|
+
DISTRIBUTION = "distribution"
|
|
57
|
+
SHAPE = "shape"
|
|
58
|
+
MAX = "max"
|
|
59
|
+
MIN = "min"
|
|
60
|
+
NORM = "norm"
|
|
61
|
+
|
|
62
|
+
level_adp = {
|
|
63
|
+
"L0": {
|
|
64
|
+
"header": [GradConst.MD5, GradConst.MAX, GradConst.MIN, GradConst.NORM, GradConst.SHAPE],
|
|
65
|
+
"have_grad_direction": False
|
|
66
|
+
},
|
|
67
|
+
"L1": {
|
|
68
|
+
"header": [GradConst.MAX, GradConst.MIN, GradConst.NORM, GradConst.SHAPE],
|
|
69
|
+
"have_grad_direction": True
|
|
70
|
+
},
|
|
71
|
+
"L2": {
|
|
72
|
+
"header": [GradConst.DISTRIBUTION, GradConst.MAX, GradConst.MIN, GradConst.NORM, GradConst.SHAPE],
|
|
73
|
+
"have_grad_direction": True
|
|
74
|
+
},
|
|
71
75
|
}
|
|
@@ -1,175 +1,170 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from typing import List
|
|
3
|
-
|
|
4
|
-
from tqdm import tqdm
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
from msprobe.core.common.
|
|
9
|
-
from msprobe.core.common.
|
|
10
|
-
from msprobe.core.
|
|
11
|
-
from msprobe.core.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
summary_csv
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
ranks
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
os.path.join(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
check_file_or_directory_path(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
plt.
|
|
85
|
-
plt.
|
|
86
|
-
plt.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
grad2
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
if grad2.dtype != bool:
|
|
172
|
-
raise TypeError(f"tensor type is not bool: {grad_file2}")
|
|
173
|
-
return grad1, grad2
|
|
174
|
-
|
|
175
|
-
|
|
1
|
+
import os
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
from tqdm import tqdm
|
|
5
|
+
import matplotlib.pyplot as plt
|
|
6
|
+
|
|
7
|
+
from msprobe.core.common.file_utils import create_directory, check_path_before_create, check_file_or_directory_path
|
|
8
|
+
from msprobe.core.common.log import logger
|
|
9
|
+
from msprobe.core.common.file_utils import remove_path, load_npy, write_csv, read_csv
|
|
10
|
+
from msprobe.core.grad_probe.constant import GradConst
|
|
11
|
+
from msprobe.core.grad_probe.utils import plt_savefig
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class GradComparator:
|
|
15
|
+
|
|
16
|
+
@staticmethod
|
|
17
|
+
def _get_grad_weight_order(path1, path2):
|
|
18
|
+
for summary_file in os.listdir(path1):
|
|
19
|
+
if not summary_file.endswith(".csv"):
|
|
20
|
+
continue
|
|
21
|
+
if not os.path.exists(os.path.join(path2, summary_file)):
|
|
22
|
+
continue
|
|
23
|
+
summary_csv = read_csv(os.path.join(path1, summary_file))
|
|
24
|
+
return summary_csv["param_name"]
|
|
25
|
+
raise RuntimeError("no matched grad_summary.csv for comparison, please dump data in same configuration")
|
|
26
|
+
|
|
27
|
+
@staticmethod
|
|
28
|
+
def _get_name_matched_grad_file(param_name, grad_files):
|
|
29
|
+
for grad_file in grad_files:
|
|
30
|
+
if param_name == grad_file[:grad_file.rfind('.')]:
|
|
31
|
+
return grad_file
|
|
32
|
+
raise RuntimeError("no matched grad_file for comparison, please dump data in same configuration")
|
|
33
|
+
|
|
34
|
+
@classmethod
|
|
35
|
+
def compare_distributed(cls, path1: str, path2: str, output_dir: str):
|
|
36
|
+
ranks = cls._get_matched_dirs(path1, path2, "rank")
|
|
37
|
+
logger.info(f"the following ranks will be compared: {ranks}")
|
|
38
|
+
if not ranks:
|
|
39
|
+
raise RuntimeError("no matched ranks for comparison, please dump data in same configuration")
|
|
40
|
+
if not os.path.isdir(output_dir):
|
|
41
|
+
create_directory(output_dir)
|
|
42
|
+
for rank in tqdm(ranks, desc="rank"):
|
|
43
|
+
logger.info(f"now comparing rank {rank}:")
|
|
44
|
+
cls.compare(os.path.join(path1, f"rank{rank}"),
|
|
45
|
+
os.path.join(path2, f"rank{rank}"),
|
|
46
|
+
os.path.join(output_dir, f"rank{rank}"))
|
|
47
|
+
|
|
48
|
+
@classmethod
|
|
49
|
+
def compare(cls, path1: str, path2: str, output_dir: str):
|
|
50
|
+
steps = cls._get_matched_dirs(path1, path2, "step")
|
|
51
|
+
if not steps:
|
|
52
|
+
raise RuntimeError("no matched steps for comparison, please dump data in same configuration")
|
|
53
|
+
similarities = cls._calculate_separated_similarities(path1, path2, steps)
|
|
54
|
+
if not os.path.isdir(output_dir):
|
|
55
|
+
create_directory(output_dir)
|
|
56
|
+
cls._save_similarities(similarities, steps, output_dir)
|
|
57
|
+
|
|
58
|
+
@classmethod
|
|
59
|
+
def _get_matched_dirs(cls, path1: str, path2: str, dir_prefix):
|
|
60
|
+
check_file_or_directory_path(path1, isdir=True)
|
|
61
|
+
check_file_or_directory_path(path2, isdir=True)
|
|
62
|
+
dirs = []
|
|
63
|
+
for dir_name in os.listdir(path1):
|
|
64
|
+
index = dir_name.replace(dir_prefix, "", 1)
|
|
65
|
+
if not dir_name.startswith(dir_prefix) or not index.isdigit():
|
|
66
|
+
continue
|
|
67
|
+
|
|
68
|
+
folder2 = os.path.join(path2, dir_name)
|
|
69
|
+
if not os.path.isdir(folder2):
|
|
70
|
+
continue
|
|
71
|
+
dirs.append(int(index))
|
|
72
|
+
dirs = sorted(dirs)
|
|
73
|
+
return dirs
|
|
74
|
+
|
|
75
|
+
@classmethod
|
|
76
|
+
def _save_similarities(cls, similarities: List[float], steps: List[int], output_dir: str):
|
|
77
|
+
if not similarities:
|
|
78
|
+
raise ValueError(f"length of similarities is 0")
|
|
79
|
+
result = [['step'] + [str(step) for step in steps]]
|
|
80
|
+
for key, value in tqdm(similarities.items(), desc="save similarities (by param)"):
|
|
81
|
+
if len(value) != len(steps):
|
|
82
|
+
raise RuntimeError(f"similarities length of {key}:{len(value)} not equal steps:{len(steps)}")
|
|
83
|
+
plt.plot(steps, value)
|
|
84
|
+
plt.xlabel('steps')
|
|
85
|
+
plt.ylabel('similarities')
|
|
86
|
+
plt.title(f'{key}_similarities')
|
|
87
|
+
picture_dir = os.path.join(output_dir, "similarities_picture")
|
|
88
|
+
if not os.path.isdir(picture_dir):
|
|
89
|
+
create_directory(picture_dir)
|
|
90
|
+
fig_save_path = os.path.join(picture_dir, f"{key}_similarities.png")
|
|
91
|
+
|
|
92
|
+
plt_savefig(fig_save_path)
|
|
93
|
+
plt.close()
|
|
94
|
+
|
|
95
|
+
result.append([key] + value)
|
|
96
|
+
result_csv_path = os.path.join(output_dir, "similarities.csv")
|
|
97
|
+
if os.path.exists(result_csv_path):
|
|
98
|
+
logger.warning(f"{result_csv_path} will be recoverd")
|
|
99
|
+
remove_path(result_csv_path)
|
|
100
|
+
write_csv(result, result_csv_path)
|
|
101
|
+
|
|
102
|
+
@classmethod
|
|
103
|
+
def _calculate_separated_similarities(cls, path1, path2, steps):
|
|
104
|
+
similarities = {}
|
|
105
|
+
logger.info(f"{len(steps)} steps will be compared")
|
|
106
|
+
grad_weight_order = cls._get_grad_weight_order(path1, path2)
|
|
107
|
+
for step in tqdm(steps, desc="culculate similarities (by step)"):
|
|
108
|
+
grad_files = cls._get_matched_grad_files(path1, path2, step)
|
|
109
|
+
same_count_summary = 0
|
|
110
|
+
total_count_summary = 0
|
|
111
|
+
for grad_name in grad_weight_order:
|
|
112
|
+
grad_file = cls._get_name_matched_grad_file(grad_name, grad_files)
|
|
113
|
+
grad1 = os.path.join(path1, f"step{step}", grad_file)
|
|
114
|
+
grad2 = os.path.join(path2, f"step{step}", grad_file)
|
|
115
|
+
same_count, total_count = cls._calculate_similarity(grad1, grad2)
|
|
116
|
+
same_count_summary += same_count
|
|
117
|
+
total_count_summary += total_count
|
|
118
|
+
idx = grad_file.rfind(".")
|
|
119
|
+
param_name = grad_file[:idx]
|
|
120
|
+
if param_name not in similarities:
|
|
121
|
+
similarities[param_name] = []
|
|
122
|
+
if total_count == 0:
|
|
123
|
+
similarities[param_name].append(0)
|
|
124
|
+
else:
|
|
125
|
+
similarities[param_name].append(same_count / total_count)
|
|
126
|
+
if GradConst.SUMMARY not in similarities:
|
|
127
|
+
similarities[GradConst.SUMMARY] = []
|
|
128
|
+
if total_count_summary == 0:
|
|
129
|
+
similarities[GradConst.SUMMARY].append(0)
|
|
130
|
+
else:
|
|
131
|
+
similarities[GradConst.SUMMARY].append(same_count_summary / total_count_summary)
|
|
132
|
+
return similarities
|
|
133
|
+
|
|
134
|
+
@classmethod
|
|
135
|
+
def _get_matched_grad_files(cls, path1: str, path2: str, step: int):
|
|
136
|
+
path1 = os.path.join(path1, f"step{step}")
|
|
137
|
+
path2 = os.path.join(path2, f"step{step}")
|
|
138
|
+
check_file_or_directory_path(path1, isdir=True)
|
|
139
|
+
check_file_or_directory_path(path2, isdir=True)
|
|
140
|
+
grad_files = []
|
|
141
|
+
for grad_file in os.listdir(path1):
|
|
142
|
+
splits = grad_file.split('.')
|
|
143
|
+
if len(splits) < 1 or splits[-1] not in GradConst.GRAD_FILE_SUFFIX:
|
|
144
|
+
continue
|
|
145
|
+
folder2 = os.path.join(path2, grad_file)
|
|
146
|
+
if not os.path.exists(folder2):
|
|
147
|
+
continue
|
|
148
|
+
grad_files.append(grad_file)
|
|
149
|
+
return sorted(grad_files)
|
|
150
|
+
|
|
151
|
+
@classmethod
|
|
152
|
+
def _calculate_similarity(cls, grad_file1: str, grad_file2: str):
|
|
153
|
+
npy1, npy2 = cls._load_grad_files(grad_file1, grad_file2)
|
|
154
|
+
same_count = (npy1 == npy2).sum()
|
|
155
|
+
total_count = npy1.size
|
|
156
|
+
return same_count, total_count
|
|
157
|
+
|
|
158
|
+
@classmethod
|
|
159
|
+
def _load_grad_files(cls, grad_file1: str, grad_file2: str):
|
|
160
|
+
grad1 = load_npy(grad_file1)
|
|
161
|
+
grad2 = load_npy(grad_file2)
|
|
162
|
+
if grad1.shape != grad2.shape:
|
|
163
|
+
raise RuntimeError(f"tensor shape is not equal: {grad_file1}, {grad_file2}")
|
|
164
|
+
if grad1.dtype != bool:
|
|
165
|
+
raise TypeError(f"tensor type is not bool: {grad_file1}")
|
|
166
|
+
if grad2.dtype != bool:
|
|
167
|
+
raise TypeError(f"tensor type is not bool: {grad_file2}")
|
|
168
|
+
return grad1, grad2
|
|
169
|
+
|
|
170
|
+
|
msprobe/core/grad_probe/utils.py
CHANGED
|
@@ -1,52 +1,77 @@
|
|
|
1
|
-
import re
|
|
2
|
-
from msprobe.core.grad_probe.constant import GradConst
|
|
3
|
-
from msprobe.core.common.log import logger
|
|
4
|
-
from msprobe.core.common.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
def
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
1
|
+
import re
|
|
2
|
+
from msprobe.core.grad_probe.constant import GradConst
|
|
3
|
+
from msprobe.core.common.log import logger
|
|
4
|
+
from msprobe.core.common.file_utils import write_csv, check_path_before_create, change_mode
|
|
5
|
+
from msprobe.core.common.const import FileCheckConst
|
|
6
|
+
import matplotlib.pyplot as plt
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def data_in_list_target(data, lst):
|
|
10
|
+
return not lst or len(lst) == 0 or data in lst
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def check_numeral_list_ascend(lst):
|
|
14
|
+
if any(not isinstance(item, (int, float)) for item in lst):
|
|
15
|
+
raise Exception("The input list should only contain numbers")
|
|
16
|
+
if lst != sorted(lst):
|
|
17
|
+
raise Exception("The input list should be ascending")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def check_param(param_name):
|
|
21
|
+
if not re.match(GradConst.PARAM_VALID_PATTERN, param_name):
|
|
22
|
+
raise RuntimeError("The parameter name contains special characters.")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def check_str(string, variable_name):
|
|
26
|
+
if not isinstance(string, str):
|
|
27
|
+
raise ValueError(f'The variable: "{variable_name}" is not a string.')
|
|
28
|
+
|
|
29
|
+
def check_bounds_element(bound):
|
|
30
|
+
return GradConst.BOUNDS_MINIMUM <= bound and bound <= GradConst.BOUNDS_MAXIMUM
|
|
31
|
+
|
|
32
|
+
def check_bounds(bounds):
|
|
33
|
+
prev = GradConst.BOUNDS_MINIMUM - 1
|
|
34
|
+
for element in bounds:
|
|
35
|
+
if not isinstance(element, (int, float)):
|
|
36
|
+
raise Exception("bounds element is not int or float")
|
|
37
|
+
if not check_bounds_element(element):
|
|
38
|
+
raise Exception("bounds element is out of int64 range")
|
|
39
|
+
if prev >= element:
|
|
40
|
+
raise Exception("bounds list is not ascending")
|
|
41
|
+
prev = element
|
|
42
|
+
|
|
43
|
+
class ListCache(list):
|
|
44
|
+
threshold = 1000
|
|
45
|
+
|
|
46
|
+
def __init__(self, *args):
|
|
47
|
+
super().__init__(*args)
|
|
48
|
+
self._output_file = None
|
|
49
|
+
|
|
50
|
+
def __del__(self):
|
|
51
|
+
self.flush()
|
|
52
|
+
|
|
53
|
+
def flush(self):
|
|
54
|
+
if len(self) == 0:
|
|
55
|
+
return
|
|
56
|
+
if not self._output_file:
|
|
57
|
+
logger.warning("dumpfile path is not setted")
|
|
58
|
+
write_csv(self, self._output_file)
|
|
59
|
+
logger.info(f"write {len(self)} items to {self._output_file}.")
|
|
60
|
+
self.clear()
|
|
61
|
+
|
|
62
|
+
def append(self, data):
|
|
63
|
+
list.append(self, data)
|
|
64
|
+
if len(self) >= ListCache.threshold:
|
|
65
|
+
self.flush()
|
|
66
|
+
|
|
67
|
+
def set_output_file(self, output_file):
|
|
68
|
+
self._output_file = output_file
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def plt_savefig(fig_save_path):
|
|
72
|
+
check_path_before_create(fig_save_path)
|
|
73
|
+
try:
|
|
74
|
+
plt.savefig(fig_save_path)
|
|
75
|
+
except Exception as e:
|
|
76
|
+
raise RuntimeError(f"save plt figure {fig_save_path} failed") from e
|
|
77
|
+
change_mode(fig_save_path, FileCheckConst.DATA_FILE_AUTHORITY)
|