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