mindspore 2.2.0__cp38-cp38-manylinux1_x86_64.whl → 2.2.10__cp38-cp38-manylinux1_x86_64.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.
Potentially problematic release.
This version of mindspore might be problematic. Click here for more details.
- mindspore/.commit_id +1 -1
- mindspore/_akg/akg/composite/build_module.py +9 -15
- mindspore/_akg/akg/utils/ascend_profilier/__init__.py +0 -0
- mindspore/_akg/akg/utils/ascend_profilier/cann_file_parser.py +76 -0
- mindspore/_akg/akg/utils/ascend_profilier/file_manager.py +56 -0
- mindspore/_akg/akg/utils/ascend_profilier/op_summary_bean.py +23 -0
- mindspore/_akg/akg/utils/ascend_profilier/op_summary_headers.py +8 -0
- mindspore/_akg/akg/utils/ascend_profilier/op_summary_parser.py +42 -0
- mindspore/_akg/akg/utils/ascend_profilier/path_manager.py +65 -0
- mindspore/_akg/akg/utils/kernel_exec.py +41 -15
- mindspore/_akg/akg/utils/tbe_codegen_utils.py +27 -6
- mindspore/_akg/akg/utils/util.py +38 -0
- mindspore/_c_dataengine.cpython-38-x86_64-linux-gnu.so +0 -0
- mindspore/_c_expression.cpython-38-x86_64-linux-gnu.so +0 -0
- mindspore/_checkparam.py +3 -3
- mindspore/_extends/graph_kernel/model/graph_split.py +84 -76
- mindspore/_extends/graph_kernel/splitter.py +3 -2
- mindspore/_extends/parallel_compile/akg_compiler/build_tbe_kernel.py +83 -66
- mindspore/_extends/parallel_compile/akg_compiler/tbe_topi.py +4 -4
- mindspore/_extends/parallel_compile/akg_compiler/util.py +10 -7
- mindspore/_extends/parallel_compile/tbe_compiler/tbe_helper.py +2 -1
- mindspore/_extends/parse/standard_method.py +2 -9
- mindspore/_extends/remote/kernel_build_server.py +2 -1
- mindspore/_mindspore_offline_debug.cpython-38-x86_64-linux-gnu.so +0 -0
- mindspore/bin/cache_admin +0 -0
- mindspore/bin/cache_server +0 -0
- mindspore/common/api.py +1 -1
- mindspore/common/auto_dynamic_shape.py +81 -85
- mindspore/common/dump.py +1 -1
- mindspore/common/tensor.py +3 -20
- mindspore/config/op_info.config +1 -1
- mindspore/context.py +11 -4
- mindspore/dataset/engine/datasets_standard_format.py +5 -0
- mindspore/dataset/vision/transforms.py +21 -21
- mindspore/experimental/optim/adam.py +1 -1
- mindspore/gen_ops.py +1 -1
- mindspore/include/api/model.h +17 -0
- mindspore/include/api/status.h +8 -3
- mindspore/lib/libdnnl.so.2 +0 -0
- mindspore/lib/libmindspore.so +0 -0
- mindspore/lib/libmindspore_backend.so +0 -0
- mindspore/lib/libmindspore_common.so +0 -0
- mindspore/lib/libmindspore_core.so +0 -0
- mindspore/lib/libmindspore_glog.so.0 +0 -0
- mindspore/lib/libmindspore_gpr.so.15 +0 -0
- mindspore/lib/libmindspore_grpc++.so.1 +0 -0
- mindspore/lib/libmindspore_grpc.so.15 +0 -0
- mindspore/lib/libmindspore_shared_lib.so +0 -0
- mindspore/lib/libnnacl.so +0 -0
- mindspore/lib/libopencv_core.so.4.5 +0 -0
- mindspore/lib/libopencv_imgcodecs.so.4.5 +0 -0
- mindspore/lib/libopencv_imgproc.so.4.5 +0 -0
- mindspore/lib/plugin/ascend/custom_aicore_ops/op_impl/ai_core/tbe/config/ascend310/aic-ascend310-ops-info.json +123 -0
- mindspore/lib/plugin/ascend/custom_aicore_ops/op_impl/ai_core/tbe/config/ascend310p/aic-ascend310p-ops-info.json +123 -0
- mindspore/lib/plugin/ascend/custom_aicore_ops/op_impl/ai_core/tbe/config/ascend910/aic-ascend910-ops-info.json +158 -0
- mindspore/lib/plugin/ascend/custom_aicore_ops/op_impl/ai_core/tbe/config/ascend910b/aic-ascend910b-ops-info.json +37 -0
- mindspore/lib/plugin/ascend/custom_aicore_ops/op_impl/ai_core/tbe/custom_aicore_ops_impl/add_dsl.py +46 -0
- mindspore/lib/plugin/ascend/custom_aicore_ops/op_impl/ai_core/tbe/custom_aicore_ops_impl/add_tik.py +51 -0
- mindspore/lib/plugin/ascend/custom_aicore_ops/op_impl/ai_core/tbe/custom_aicore_ops_impl/kv_cache_mgr.py +241 -0
- mindspore/lib/plugin/ascend/custom_aicore_ops/op_impl/ai_core/tbe/custom_aicore_ops_impl/matmul_tik.py +212 -0
- mindspore/lib/plugin/ascend/custom_aicore_ops/op_impl/vector_core/tbe/custom_aicore_ops_impl/add_dsl.py +46 -0
- mindspore/lib/plugin/ascend/custom_aicore_ops/op_impl/vector_core/tbe/custom_aicore_ops_impl/add_tik.py +51 -0
- mindspore/lib/plugin/ascend/custom_aicore_ops/op_impl/vector_core/tbe/custom_aicore_ops_impl/kv_cache_mgr.py +241 -0
- mindspore/lib/plugin/ascend/custom_aicore_ops/op_impl/vector_core/tbe/custom_aicore_ops_impl/matmul_tik.py +212 -0
- mindspore/lib/plugin/ascend/custom_aicore_ops/op_proto/libop_proto.so +0 -0
- mindspore/lib/plugin/ascend/custom_aicpu_ops/op_impl/cpu/aicpu_kernel/impl/libcust_aicpu_kernels.so +0 -0
- mindspore/lib/plugin/ascend/custom_aicpu_ops/op_impl/cpu/aicpu_kernel/impl/libcust_cpu_kernels.so +0 -0
- mindspore/lib/plugin/ascend/custom_aicpu_ops/op_impl/cpu/config/cust_aicpu_kernel.json +8 -80
- mindspore/lib/plugin/ascend/custom_aicpu_ops/op_proto/libcust_op_proto.so +0 -0
- mindspore/lib/plugin/ascend/libakg.so +0 -0
- mindspore/lib/plugin/ascend/libhccl_plugin.so +0 -0
- mindspore/lib/plugin/ascend/libmindspore_aicpu_kernels.so +0 -0
- mindspore/lib/plugin/ascend/libmindspore_cpu_kernels.so +0 -0
- mindspore/lib/plugin/cpu/libakg.so +0 -0
- mindspore/lib/plugin/gpu/libcuda_ops.so.10 +0 -0
- mindspore/lib/plugin/gpu/libcuda_ops.so.11 +0 -0
- mindspore/lib/plugin/gpu10.1/libakg.so +0 -0
- mindspore/lib/plugin/gpu10.1/libnccl.so.2 +0 -0
- mindspore/lib/plugin/gpu11.1/libakg.so +0 -0
- mindspore/lib/plugin/gpu11.1/libnccl.so.2 +0 -0
- mindspore/lib/plugin/gpu11.6/libakg.so +0 -0
- mindspore/lib/plugin/gpu11.6/libnccl.so.2 +0 -0
- mindspore/lib/plugin/libmindspore_ascend.so.1 +0 -0
- mindspore/lib/plugin/libmindspore_ascend.so.2 +0 -0
- mindspore/lib/plugin/libmindspore_gpu.so.10.1 +0 -0
- mindspore/lib/plugin/libmindspore_gpu.so.11.1 +0 -0
- mindspore/lib/plugin/libmindspore_gpu.so.11.6 +0 -0
- mindspore/nn/cell.py +0 -3
- mindspore/nn/layer/activation.py +4 -5
- mindspore/nn/layer/conv.py +39 -23
- mindspore/nn/layer/flash_attention.py +90 -78
- mindspore/nn/layer/math.py +3 -7
- mindspore/nn/layer/rnn_cells.py +5 -5
- mindspore/nn/wrap/cell_wrapper.py +6 -0
- mindspore/numpy/utils_const.py +5 -5
- mindspore/ops/_grad_experimental/grad_array_ops.py +1 -1
- mindspore/ops/_grad_experimental/grad_implementations.py +2 -2
- mindspore/ops/_grad_experimental/grad_math_ops.py +19 -18
- mindspore/ops/_grad_experimental/grad_sparse_ops.py +3 -3
- mindspore/ops/_op_impl/aicpu/add.py +3 -3
- mindspore/ops/_utils/utils.py +2 -0
- mindspore/ops/composite/multitype_ops/_compile_utils.py +2 -1
- mindspore/ops/composite/multitype_ops/getitem_impl.py +2 -2
- mindspore/ops/function/array_func.py +10 -7
- mindspore/ops/function/grad/grad_func.py +0 -1
- mindspore/ops/function/nn_func.py +98 -9
- mindspore/ops/function/random_func.py +2 -1
- mindspore/ops/op_info_register.py +24 -21
- mindspore/ops/operations/__init__.py +3 -2
- mindspore/ops/operations/_grad_ops.py +24 -4
- mindspore/ops/operations/_inner_ops.py +155 -23
- mindspore/ops/operations/array_ops.py +9 -7
- mindspore/ops/operations/comm_ops.py +2 -2
- mindspore/ops/operations/custom_ops.py +85 -68
- mindspore/ops/operations/inner_ops.py +26 -3
- mindspore/ops/operations/math_ops.py +4 -3
- mindspore/ops/operations/nn_ops.py +109 -28
- mindspore/parallel/_parallel_serialization.py +10 -3
- mindspore/parallel/_tensor.py +4 -1
- mindspore/parallel/checkpoint_transform.py +13 -2
- mindspore/parallel/shard.py +17 -10
- mindspore/profiler/common/util.py +1 -0
- mindspore/profiler/parser/ascend_hccl_generator.py +232 -0
- mindspore/profiler/parser/ascend_msprof_exporter.py +86 -43
- mindspore/profiler/parser/ascend_msprof_generator.py +196 -9
- mindspore/profiler/parser/ascend_op_generator.py +1 -1
- mindspore/profiler/parser/ascend_timeline_generator.py +6 -182
- mindspore/profiler/parser/base_timeline_generator.py +1 -1
- mindspore/profiler/parser/cpu_gpu_timeline_generator.py +2 -2
- mindspore/profiler/parser/framework_parser.py +1 -1
- mindspore/profiler/parser/profiler_info.py +19 -0
- mindspore/profiler/profiling.py +46 -24
- mindspore/rewrite/api/pattern_engine.py +1 -1
- mindspore/rewrite/parsers/for_parser.py +1 -1
- mindspore/rewrite/symbol_tree.py +1 -4
- mindspore/run_check/_check_version.py +5 -3
- mindspore/safeguard/rewrite_obfuscation.py +52 -28
- mindspore/train/callback/_summary_collector.py +1 -1
- mindspore/train/dataset_helper.py +1 -0
- mindspore/train/model.py +2 -2
- mindspore/train/serialization.py +97 -11
- mindspore/train/summary/_summary_adapter.py +1 -1
- mindspore/train/summary/summary_record.py +23 -7
- mindspore/version.py +1 -1
- {mindspore-2.2.0.dist-info → mindspore-2.2.10.dist-info}/METADATA +1 -1
- {mindspore-2.2.0.dist-info → mindspore-2.2.10.dist-info}/RECORD +149 -129
- {mindspore-2.2.0.dist-info → mindspore-2.2.10.dist-info}/WHEEL +0 -0
- {mindspore-2.2.0.dist-info → mindspore-2.2.10.dist-info}/entry_points.txt +0 -0
- {mindspore-2.2.0.dist-info → mindspore-2.2.10.dist-info}/top_level.txt +0 -0
mindspore/.commit_id
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__commit_id__ = '[sha1]:
|
|
1
|
+
__commit_id__ = '[sha1]:93fa4635,[branch]:(HEAD,origin/r2.2.10-1,r2.2.10-1)'
|
|
@@ -21,14 +21,14 @@ from collections.abc import Iterable
|
|
|
21
21
|
import akg
|
|
22
22
|
from akg import tvm
|
|
23
23
|
from tvm.autotvm.env import AutotvmGlobalScope
|
|
24
|
+
from akg.utils.util import parse_workspace_map
|
|
24
25
|
from akg.utils.tbe_codegen_utils import build_tbe_codegen
|
|
25
26
|
from akg.utils.kernel_exec import ReturnType, is_symbolic_tiling
|
|
26
27
|
from .split_stitch import split_stitch_attr
|
|
27
28
|
from .construct_args import ConstructType, ConstructKey
|
|
28
29
|
from .construct_args import get_construct_args, get_tune_construct_args, \
|
|
29
30
|
should_enable_attr, get_stmt_for_tune, add_attrs_in_segment_infos
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
from utils.util import get_ascend_type
|
|
32
32
|
def generate_trait(desc):
|
|
33
33
|
"""
|
|
34
34
|
generate trait of kernel description
|
|
@@ -523,17 +523,6 @@ def _build_to_module(desc_s, desc_d, attrs=None, poly=True):
|
|
|
523
523
|
|
|
524
524
|
return _cpp_build(attrs, process, poly, segment_tree, segment_infos)
|
|
525
525
|
|
|
526
|
-
|
|
527
|
-
def _get_ascend_type(desc):
|
|
528
|
-
if "target_info" not in desc.keys():
|
|
529
|
-
return None
|
|
530
|
-
|
|
531
|
-
target_info_type = desc["target_info"]
|
|
532
|
-
if target_info_type.get("arch"):
|
|
533
|
-
return target_info_type.get("arch")
|
|
534
|
-
return None
|
|
535
|
-
|
|
536
|
-
|
|
537
526
|
def _build_to_module_ascend(desc_s_in, desc_d_in, attr, use_repo=True):
|
|
538
527
|
"""
|
|
539
528
|
build kernel with compute description in json format
|
|
@@ -650,7 +639,7 @@ def _build_to_module_ascend(desc_s_in, desc_d_in, attr, use_repo=True):
|
|
|
650
639
|
ConstructType.NORMAL: _normal_postprocess,
|
|
651
640
|
}
|
|
652
641
|
process = desc_d_in["process"]
|
|
653
|
-
ascend_type =
|
|
642
|
+
ascend_type = get_ascend_type(desc_d_in)
|
|
654
643
|
ascend_type_to_section = {"Ascend910A": "1.6", "Ascend310P3": "1.7",
|
|
655
644
|
"Ascend910B1": "2.1", "Ascend910B2": "2.2", "Ascend910B3": "2.3", "Ascend910B4": "2.4"}
|
|
656
645
|
if ascend_type is not None:
|
|
@@ -659,6 +648,7 @@ def _build_to_module_ascend(desc_s_in, desc_d_in, attr, use_repo=True):
|
|
|
659
648
|
config_func(section)
|
|
660
649
|
if section >= "2.1":
|
|
661
650
|
attr["is_tbe_codegen"] = True
|
|
651
|
+
attr["pragma_modshift"] = True
|
|
662
652
|
segment_tree, segment_infos = get_construct_args(desc_s_in, attr, post_funcs)
|
|
663
653
|
poly = True
|
|
664
654
|
res = _cpp_build(attr, process, poly, segment_tree, segment_infos)
|
|
@@ -668,8 +658,12 @@ def _build_to_module_ascend(desc_s_in, desc_d_in, attr, use_repo=True):
|
|
|
668
658
|
args_json = []
|
|
669
659
|
for buf in res[1]:
|
|
670
660
|
args_json.append(akg.tvm.save_json(buf, "0.8.0"))
|
|
661
|
+
|
|
662
|
+
workspace_dict = parse_workspace_map(res[2])
|
|
663
|
+
if workspace_dict is not None:
|
|
664
|
+
attr["workspace"] = workspace_dict
|
|
671
665
|
|
|
672
|
-
is_success = build_tbe_codegen(kernel_name, stmt_json, args_json,
|
|
666
|
+
is_success = build_tbe_codegen(kernel_name, stmt_json, args_json, attr, ascend_type)
|
|
673
667
|
if not is_success:
|
|
674
668
|
raise TypeError("npu_inference codegen failed.")
|
|
675
669
|
return kernel_name
|
|
File without changes
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import re
|
|
3
|
+
import subprocess
|
|
4
|
+
from enum import Enum
|
|
5
|
+
|
|
6
|
+
from .file_manager import FileManager
|
|
7
|
+
from .path_manager import PathManager
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class CANNDataEnum(Enum):
|
|
11
|
+
OP_SUMMARY = 0
|
|
12
|
+
NPU_MEMORY = 1
|
|
13
|
+
MSPROF_TIMELINE = 2
|
|
14
|
+
STEP_TRACE = 3
|
|
15
|
+
GE_MEMORY_RECORD = 4
|
|
16
|
+
GE_OPERATOR_MEMORY = 5
|
|
17
|
+
L2_CACHE = 6
|
|
18
|
+
AI_CPU = 7
|
|
19
|
+
COMMUNICATION = 8
|
|
20
|
+
MATRIX = 9
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class CANNFileParser:
|
|
24
|
+
COMMAND_SUCCESS = 0
|
|
25
|
+
ACL_TO_NPU = "acl_to_npu"
|
|
26
|
+
START_FLOW = "s"
|
|
27
|
+
END_FLOW = "f"
|
|
28
|
+
SUMMARY = "summary"
|
|
29
|
+
TIMELINE = "timeline"
|
|
30
|
+
ANALYZE = "analyze"
|
|
31
|
+
CANN_DATA_MATCH = {
|
|
32
|
+
CANNDataEnum.OP_SUMMARY: [r"^op_summary_\d+_\d+\.csv", r"^op_summary_\d+_\d+_\d+\.csv",
|
|
33
|
+
r"^op_summary_\d+_\d+_\d+_\d+\.csv"],
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
def __init__(self, profiler_path: str):
|
|
37
|
+
self._cann_path = PathManager.get_cann_path(profiler_path)
|
|
38
|
+
self._file_dict = {}
|
|
39
|
+
self._file_dispatch()
|
|
40
|
+
|
|
41
|
+
def export_cann_profiling(self):
|
|
42
|
+
if not os.path.isdir(self._cann_path):
|
|
43
|
+
return
|
|
44
|
+
self._del_summary_and_timeline_data()
|
|
45
|
+
completed_process = subprocess.run(["msprof", "--export=on", f"--output={self._cann_path}"],
|
|
46
|
+
capture_output=True)
|
|
47
|
+
if completed_process.returncode != self.COMMAND_SUCCESS:
|
|
48
|
+
raise RuntimeError(
|
|
49
|
+
f"Export CANN Profiling data failed, please verify that the ascend-toolkit is installed and set-env.sh "
|
|
50
|
+
f"is sourced. or you can execute the command to confirm the CANN Profiling export result: "
|
|
51
|
+
f"msprof --export=on --output={self._cann_path}")
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def get_file_list_by_type(self, file_type: CANNDataEnum) -> set:
|
|
55
|
+
return self._file_dict.get(file_type, set())
|
|
56
|
+
|
|
57
|
+
def _file_dispatch(self):
|
|
58
|
+
all_file_list = PathManager.get_device_all_file_list_by_type(self._cann_path, self.SUMMARY)
|
|
59
|
+
all_file_list += PathManager.get_device_all_file_list_by_type(self._cann_path, self.TIMELINE)
|
|
60
|
+
all_file_list += PathManager.get_analyze_all_file(self._cann_path, self.ANALYZE)
|
|
61
|
+
for file_path in all_file_list:
|
|
62
|
+
if not os.path.isfile(file_path):
|
|
63
|
+
continue
|
|
64
|
+
for data_type, re_match_exp_list in self.CANN_DATA_MATCH.items():
|
|
65
|
+
for re_match_exp in re_match_exp_list:
|
|
66
|
+
if re.match(re_match_exp, os.path.basename(file_path)):
|
|
67
|
+
self._file_dict.setdefault(data_type, set()).add(file_path)
|
|
68
|
+
|
|
69
|
+
def _del_summary_and_timeline_data(self):
|
|
70
|
+
device_path = PathManager.get_device_path(self._cann_path)
|
|
71
|
+
if not device_path:
|
|
72
|
+
return
|
|
73
|
+
summary_path = os.path.join(device_path, "summary")
|
|
74
|
+
timeline_path = os.path.join(device_path, "timeline")
|
|
75
|
+
FileManager.remove_file_safety(summary_path)
|
|
76
|
+
FileManager.remove_file_safety(timeline_path)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import csv
|
|
2
|
+
import json
|
|
3
|
+
import os.path
|
|
4
|
+
import shutil
|
|
5
|
+
from warnings import warn
|
|
6
|
+
|
|
7
|
+
MAX_FILE_SIZE = 1024 * 1024 * 1024 * 10
|
|
8
|
+
MAX_CSV_SIZE = 1024 * 1024 * 1024 * 5
|
|
9
|
+
|
|
10
|
+
class FileManager:
|
|
11
|
+
@classmethod
|
|
12
|
+
def file_read_all(cls, file_path: str, mode: str = "r") -> any:
|
|
13
|
+
if not os.path.isfile(file_path):
|
|
14
|
+
return ''
|
|
15
|
+
file_size = os.path.getsize(file_path)
|
|
16
|
+
if file_size <= 0:
|
|
17
|
+
return ''
|
|
18
|
+
if file_size > MAX_FILE_SIZE:
|
|
19
|
+
warn(f"The file size exceeds the preset value {MAX_FILE_SIZE / 1024 / 1024}MB, "
|
|
20
|
+
f"please check the file: {file_path}")
|
|
21
|
+
return ''
|
|
22
|
+
try:
|
|
23
|
+
with open(file_path, mode) as file:
|
|
24
|
+
return file.read()
|
|
25
|
+
except Exception:
|
|
26
|
+
raise RuntimeError(f"Can't read file: {file_path}")
|
|
27
|
+
|
|
28
|
+
@classmethod
|
|
29
|
+
def read_csv_file(cls, file_path: str, class_bean: any) -> list:
|
|
30
|
+
if not os.path.isfile(file_path):
|
|
31
|
+
return []
|
|
32
|
+
file_size = os.path.getsize(file_path)
|
|
33
|
+
if file_size <= 0:
|
|
34
|
+
return []
|
|
35
|
+
if file_size > MAX_CSV_SIZE:
|
|
36
|
+
warn(f"The file size exceeds the preset value {MAX_CSV_SIZE / 1024 / 1024}MB, "
|
|
37
|
+
f"please check the file: {file_path}")
|
|
38
|
+
return []
|
|
39
|
+
result_data = []
|
|
40
|
+
try:
|
|
41
|
+
with open(file_path, newline="") as csv_file:
|
|
42
|
+
reader = csv.DictReader(csv_file)
|
|
43
|
+
for row in reader:
|
|
44
|
+
result_data.append(class_bean(row))
|
|
45
|
+
except Exception:
|
|
46
|
+
raise RuntimeError(f"Failed to read the file: {file_path}")
|
|
47
|
+
return result_data
|
|
48
|
+
|
|
49
|
+
@classmethod
|
|
50
|
+
def remove_file_safety(cls, path: str):
|
|
51
|
+
if os.path.exists(path):
|
|
52
|
+
try:
|
|
53
|
+
shutil.rmtree(path)
|
|
54
|
+
except Exception:
|
|
55
|
+
print(f"[WARNING] [{os.getpid()}] profiler.py: Can't remove the directory: {path}")
|
|
56
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from .op_summary_headers import OpSummaryHeaders
|
|
2
|
+
|
|
3
|
+
class OpSummaryBean:
|
|
4
|
+
headers = []
|
|
5
|
+
|
|
6
|
+
def __init__(self, data: list):
|
|
7
|
+
self._data = data
|
|
8
|
+
|
|
9
|
+
@property
|
|
10
|
+
def row(self) -> list:
|
|
11
|
+
row = []
|
|
12
|
+
read_headers = OpSummaryBean.headers if OpSummaryBean.headers else self._data.keys()
|
|
13
|
+
for field_name in read_headers:
|
|
14
|
+
row.append(self._data.get(field_name, ""))
|
|
15
|
+
return row
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def ts(self) -> float:
|
|
19
|
+
return float(self._data.get(OpSummaryHeaders.TASK_START_TIME, 0))
|
|
20
|
+
|
|
21
|
+
@property
|
|
22
|
+
def all_headers(self) -> list:
|
|
23
|
+
return list(self._data.keys())
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
class OpSummaryHeaders(object):
|
|
2
|
+
# op_summary
|
|
3
|
+
TASK_START_TIME = "Task Start Time(us)"
|
|
4
|
+
AIC_TOTAL_CYCLES = "aic_total_cycles"
|
|
5
|
+
AIV_TOTAL_CYCLES = "aiv_total_cycles"
|
|
6
|
+
TASK_DURATION = "Task Duration(us)"
|
|
7
|
+
OP_SUMMARY_SHOW_HEADERS = ["Op Name", "OP Type", "Task Type", TASK_START_TIME, TASK_DURATION,
|
|
8
|
+
"Task Wait Time(us)", "Block Dim" ,AIC_TOTAL_CYCLES, AIV_TOTAL_CYCLES]
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from .op_summary_headers import OpSummaryHeaders
|
|
2
|
+
from .file_manager import FileManager
|
|
3
|
+
from .op_summary_bean import OpSummaryBean
|
|
4
|
+
from .cann_file_parser import CANNFileParser, CANNDataEnum
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class OpSummaryParser():
|
|
8
|
+
|
|
9
|
+
def __init__(self, profiler_path: str):
|
|
10
|
+
self._profiler_path = profiler_path
|
|
11
|
+
|
|
12
|
+
@classmethod
|
|
13
|
+
def _project_map_for_headers(cls, input_headers: list):
|
|
14
|
+
project_map_dict = {OpSummaryHeaders.OP_SUMMARY_SHOW_HEADERS[i]: OpSummaryHeaders.OP_SUMMARY_KERNEL_BASE_HEADERS[i] for i in
|
|
15
|
+
range(len(OpSummaryHeaders.OP_SUMMARY_SHOW_HEADERS))}
|
|
16
|
+
output_headers = []
|
|
17
|
+
for header in input_headers:
|
|
18
|
+
if header in project_map_dict:
|
|
19
|
+
output_headers.append(project_map_dict.get(header))
|
|
20
|
+
else:
|
|
21
|
+
output_headers.append(header)
|
|
22
|
+
return output_headers
|
|
23
|
+
|
|
24
|
+
def generate_op_summary_data(self) -> dict:
|
|
25
|
+
op_summary_file_set = CANNFileParser(self._profiler_path).get_file_list_by_type(CANNDataEnum.OP_SUMMARY)
|
|
26
|
+
summary_data = []
|
|
27
|
+
for file_path in op_summary_file_set:
|
|
28
|
+
all_data = FileManager.read_csv_file(file_path, OpSummaryBean)
|
|
29
|
+
if all_data:
|
|
30
|
+
OpSummaryBean.headers = OpSummaryHeaders.OP_SUMMARY_SHOW_HEADERS
|
|
31
|
+
output_headers = OpSummaryBean.headers
|
|
32
|
+
summary_data.extend([data.row for data in all_data])
|
|
33
|
+
else:
|
|
34
|
+
raise RuntimeError("parse op summary csv failed.")
|
|
35
|
+
|
|
36
|
+
return self.create_dict(summary_data[0],output_headers)
|
|
37
|
+
|
|
38
|
+
def create_dict(self,summary_data,headers):
|
|
39
|
+
summary_dict={}
|
|
40
|
+
for i in range(len(summary_data)):
|
|
41
|
+
summary_dict[headers[i]] = summary_data[i]
|
|
42
|
+
return summary_dict
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import re
|
|
3
|
+
|
|
4
|
+
class PathManager:
|
|
5
|
+
|
|
6
|
+
@classmethod
|
|
7
|
+
def get_cann_path(cls, profiler_path: str) -> str:
|
|
8
|
+
sub_dirs = os.listdir(os.path.realpath(profiler_path))
|
|
9
|
+
for sub_dir in sub_dirs:
|
|
10
|
+
sub_path = os.path.join(profiler_path, sub_dir)
|
|
11
|
+
if os.path.isdir(sub_path) and re.match(r"^PROF_\d+_\d+_[a-zA-Z]+", sub_dir):
|
|
12
|
+
return sub_path
|
|
13
|
+
return ""
|
|
14
|
+
|
|
15
|
+
@classmethod
|
|
16
|
+
def get_device_path(cls, cann_path: str) -> str:
|
|
17
|
+
sub_dirs = os.listdir(os.path.realpath(cann_path))
|
|
18
|
+
for sub_dir in sub_dirs:
|
|
19
|
+
sub_path = os.path.join(cann_path, sub_dir)
|
|
20
|
+
if os.path.isdir(sub_path) and re.match(r"^device_\d", sub_dir):
|
|
21
|
+
return sub_path
|
|
22
|
+
return ""
|
|
23
|
+
|
|
24
|
+
@classmethod
|
|
25
|
+
def get_start_info_path(cls, cann_path: str) -> str:
|
|
26
|
+
start_info_path = os.path.join(cann_path, "host", "start_info")
|
|
27
|
+
if os.path.exists(start_info_path):
|
|
28
|
+
return start_info_path
|
|
29
|
+
device_path = cls.get_device_path(cann_path)
|
|
30
|
+
if not device_path:
|
|
31
|
+
return ""
|
|
32
|
+
device_path_split = os.path.basename(device_path).split("_")
|
|
33
|
+
if len(device_path_split) != 2:
|
|
34
|
+
return ""
|
|
35
|
+
start_info_file = f"start_info.{device_path_split[1]}"
|
|
36
|
+
start_info_path = os.path.join(device_path, start_info_file)
|
|
37
|
+
if os.path.exists(start_info_path):
|
|
38
|
+
return start_info_path
|
|
39
|
+
return ""
|
|
40
|
+
|
|
41
|
+
@classmethod
|
|
42
|
+
def get_device_all_file_list_by_type(cls, profiler_path: str, summary_or_timeline: str) -> list:
|
|
43
|
+
file_list = []
|
|
44
|
+
_path = os.path.join(cls.get_device_path(profiler_path), summary_or_timeline)
|
|
45
|
+
if not os.path.isdir(_path):
|
|
46
|
+
return file_list
|
|
47
|
+
sub_files = os.listdir(os.path.realpath(_path))
|
|
48
|
+
if not sub_files:
|
|
49
|
+
return file_list
|
|
50
|
+
for sub_file in sub_files:
|
|
51
|
+
file_list.append(os.path.join(_path, sub_file))
|
|
52
|
+
return file_list
|
|
53
|
+
|
|
54
|
+
@classmethod
|
|
55
|
+
def get_analyze_all_file(cls, profiler_path: str, analyze: str) -> list:
|
|
56
|
+
file_list = []
|
|
57
|
+
_path = os.path.join(profiler_path, analyze)
|
|
58
|
+
if not os.path.isdir(_path):
|
|
59
|
+
return file_list
|
|
60
|
+
sub_files = os.listdir(os.path.realpath(_path))
|
|
61
|
+
if not sub_files:
|
|
62
|
+
return file_list
|
|
63
|
+
for sub_file in sub_files:
|
|
64
|
+
file_list.append(os.path.join(_path, sub_file))
|
|
65
|
+
return file_list
|
|
@@ -43,10 +43,12 @@ from akg.utils import custom_tiling as ct_util
|
|
|
43
43
|
from akg.utils import validation_check as vc_util
|
|
44
44
|
from akg.utils.dsl_create import TensorUtils
|
|
45
45
|
from akg.utils.util import parse_kwargs
|
|
46
|
-
from akg.backend.parsing_profiling_data import HWTSLogParser
|
|
46
|
+
from akg.backend.parsing_profiling_data import HWTSLogParser, max_time_consume
|
|
47
47
|
from akg.backend.parsing_profiling_data import validate_and_normalize_path
|
|
48
48
|
from akg.backend import aic_model
|
|
49
|
-
|
|
49
|
+
from .ascend_profilier.cann_file_parser import CANNFileParser
|
|
50
|
+
from .ascend_profilier.op_summary_parser import OpSummaryParser
|
|
51
|
+
from .ascend_profilier.op_summary_headers import OpSummaryHeaders
|
|
50
52
|
sh = logging.StreamHandler(sys.stdout)
|
|
51
53
|
logging.getLogger().addHandler(sh)
|
|
52
54
|
logging.getLogger().setLevel(logging.INFO)
|
|
@@ -169,7 +171,7 @@ def gen_name_kernel(kernel, dtype, shapes):
|
|
|
169
171
|
return res
|
|
170
172
|
|
|
171
173
|
|
|
172
|
-
def profiling_mode_run(kernel_name, args, outputs, tuning, device_id):
|
|
174
|
+
def profiling_mode_run(kernel_name, args, outputs, tuning, device_id, arch=None):
|
|
173
175
|
"""
|
|
174
176
|
Function for collecting cycle data from device.
|
|
175
177
|
|
|
@@ -180,21 +182,45 @@ def profiling_mode_run(kernel_name, args, outputs, tuning, device_id):
|
|
|
180
182
|
tuning: tuning model.
|
|
181
183
|
device_id: device_id on device.
|
|
182
184
|
"""
|
|
183
|
-
akg.tvm.get_global_func("ascend_start_profiling")(
|
|
185
|
+
akg.tvm.get_global_func("ascend_start_profiling")(kernel_name)
|
|
184
186
|
time_before_launch = time.time()
|
|
185
187
|
output_data = ascend_run(kernel_name, args, outputs, device_id)
|
|
186
188
|
akg.tvm.get_global_func("ascend_stop_profiling")()
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
189
|
+
cycle = 0
|
|
190
|
+
if arch is not None and "910B" in arch:
|
|
191
|
+
# for ascend910B profiling
|
|
192
|
+
cycle = profiling_analyse_910B(time_before_launch)
|
|
193
|
+
else:
|
|
194
|
+
cycle = profiling_analyse(device_id, time_before_launch)
|
|
195
|
+
logging.info('=====Task Duration(us)==============================')
|
|
190
196
|
if cycle != PROF_ERROR_CODE:
|
|
191
197
|
logging.info(cycle)
|
|
192
198
|
else:
|
|
193
|
-
logging.error("OOPS, can't correctly
|
|
199
|
+
logging.error("OOPS, can't correctly Task Duration!")
|
|
194
200
|
TestUtils.record_cycle(cycle)
|
|
195
|
-
logging.info('=====
|
|
201
|
+
logging.info('=====Task Duration(us)==============================')
|
|
196
202
|
return output_data, {'run_time': cycle}
|
|
197
203
|
|
|
204
|
+
def profiling_analyse_910B(time_before_launch):
|
|
205
|
+
public_path = os.getenv('PROFILING_DIR')
|
|
206
|
+
if public_path is None:
|
|
207
|
+
raise RuntimeError("Environment PROFILING_DIR not set!")
|
|
208
|
+
public_path = validate_and_normalize_path(public_path)
|
|
209
|
+
CANNFileParser(public_path).export_cann_profiling()
|
|
210
|
+
cann_file_parser = OpSummaryParser(public_path)
|
|
211
|
+
profiler_file = cann_file_parser._profiler_path
|
|
212
|
+
logging.debug("prof file is: %s", os.path.basename(profiler_file))
|
|
213
|
+
file_create_time = os.path.getctime(profiler_file)
|
|
214
|
+
if file_create_time < time_before_launch:
|
|
215
|
+
raise RuntimeError("The PROF file is too old")
|
|
216
|
+
datas:dict = cann_file_parser.generate_op_summary_data()
|
|
217
|
+
task_duration = float(datas.get(OpSummaryHeaders.TASK_DURATION,max_time_consume))
|
|
218
|
+
# # aic_total_cycles means ai core cycle
|
|
219
|
+
# # aiv_total_cycles means ai vector cycle
|
|
220
|
+
# aiv_total_cycle = int(datas.get(OpSummaryHeaders.AIV_TOTAL_CYCLES,max_time_consume))
|
|
221
|
+
# aic_total_cycle = int(datas.get(OpSummaryHeaders.AIC_TOTAL_CYCLES,max_time_consume))
|
|
222
|
+
# return aiv_total_cycle+aic_total_cycle
|
|
223
|
+
return task_duration
|
|
198
224
|
|
|
199
225
|
def profiling_analyse(device_id, time_before_launch):
|
|
200
226
|
"""analyse profiling."""
|
|
@@ -348,12 +374,12 @@ def get_kernel_name_from_mod(mod):
|
|
|
348
374
|
return kernel_name
|
|
349
375
|
|
|
350
376
|
|
|
351
|
-
def mod_launch_ascend_profiling(mod, args, outputs=(-1,), tuning=False, device_id=-1):
|
|
377
|
+
def mod_launch_ascend_profiling(mod, args, outputs=(-1,), tuning=False, device_id=-1, arch=None):
|
|
352
378
|
gc.collect()
|
|
353
379
|
if device_id == -1:
|
|
354
380
|
device_id = int(os.environ.get("DEVICE_ID", 0))
|
|
355
381
|
kernel_name = get_kernel_name_from_mod(mod)
|
|
356
|
-
return profiling_mode_run(kernel_name, args, outputs, tuning, device_id)
|
|
382
|
+
return profiling_mode_run(kernel_name, args, outputs, tuning, device_id, arch=arch)
|
|
357
383
|
|
|
358
384
|
|
|
359
385
|
def mod_launch_default(mod, args, outputs=(-1,), target=CUDA, tuning=False, device_id=-1, repeat_time=400):
|
|
@@ -387,7 +413,7 @@ def mod_launch_default(mod, args, outputs=(-1,), target=CUDA, tuning=False, devi
|
|
|
387
413
|
|
|
388
414
|
|
|
389
415
|
@func_time_required
|
|
390
|
-
def mod_launch(mod, args, outputs=(-1,), tuning=False, device_id=-1, expect=None, repeat_time=400):
|
|
416
|
+
def mod_launch(mod, args, outputs=(-1,), tuning=False, device_id=-1, expect=None, repeat_time=400, arch=None):
|
|
391
417
|
"""
|
|
392
418
|
unified run CCE kernel api.
|
|
393
419
|
|
|
@@ -398,7 +424,7 @@ def mod_launch(mod, args, outputs=(-1,), tuning=False, device_id=-1, expect=None
|
|
|
398
424
|
tuning (bool): tuning model.
|
|
399
425
|
device_id: device_id on device.
|
|
400
426
|
expect: when mode in ["compile_cloud", "compile_mini"], return it.
|
|
401
|
-
|
|
427
|
+
arch: Ascend arch type
|
|
402
428
|
Returns:
|
|
403
429
|
output numpy array, or tuple of numpy array if multi-output.
|
|
404
430
|
"""
|
|
@@ -414,7 +440,7 @@ def mod_launch(mod, args, outputs=(-1,), tuning=False, device_id=-1, expect=None
|
|
|
414
440
|
run_args = [kernel_name, args, outputs, device_id]
|
|
415
441
|
if os.environ.get("PROFILING_MODE") == "true":
|
|
416
442
|
run_func = profiling_mode_run
|
|
417
|
-
run_args = [kernel_name, args, outputs, tuning, device_id]
|
|
443
|
+
run_args = [kernel_name, args, outputs, tuning, device_id, arch]
|
|
418
444
|
if os.environ.get("PROFILING_DIR", None) is None:
|
|
419
445
|
os.environ["PROFILING_DIR"] = "."
|
|
420
446
|
logging.info("[RUNTIME_WARNING] In profiling mode, while profiling dir is not set!Set to current dir by default.")
|
|
@@ -1031,7 +1057,7 @@ def npu_op_build(s, op_var, shape_var, kernel_name="", binds=None, attrs=None,
|
|
|
1031
1057
|
for buf in enumerate(arg_list):
|
|
1032
1058
|
args_json.append(akg.tvm.save_json(buf, "0.8.0"))
|
|
1033
1059
|
|
|
1034
|
-
is_success = build_tbe_codegen(kernel_name, json_str, args_json, attrs
|
|
1060
|
+
is_success = build_tbe_codegen(kernel_name, json_str, args_json, attrs)
|
|
1035
1061
|
if not is_success:
|
|
1036
1062
|
raise TypeError("npu_inference codegen failed.")
|
|
1037
1063
|
return kernel_name
|
|
@@ -15,22 +15,40 @@
|
|
|
15
15
|
# limitations under the License.
|
|
16
16
|
import os
|
|
17
17
|
import logging
|
|
18
|
+
from akg.utils.util import write_code
|
|
19
|
+
import json
|
|
18
20
|
|
|
19
21
|
logging.getLogger().setLevel(logging.INFO)
|
|
20
22
|
|
|
23
|
+
def create_directory(dir):
|
|
24
|
+
if not os.path.exists(dir):
|
|
25
|
+
os.mkdir(dir)
|
|
21
26
|
|
|
22
|
-
def
|
|
23
|
-
|
|
27
|
+
def set_workspace_for_json(json_path, workspace_dict):
|
|
28
|
+
if workspace_dict is None:
|
|
29
|
+
return
|
|
30
|
+
with open(json_path, 'r') as f:
|
|
31
|
+
js_info = json.loads(f.read())
|
|
32
|
+
js_info["workspace"] = workspace_dict
|
|
33
|
+
write_code(js_info, json_path)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def copy_to_akg_kernel_meta(kernel_name, postfixs, workspace_dict=None):
|
|
37
|
+
akg_kernel_mate_str = os.getenv("KERNEL_META_DIR",default="akg_kernel_meta")
|
|
24
38
|
source = os.path.realpath(os.getenv('MS_COMPILER_CACHE_PATH', './'))
|
|
25
39
|
import shutil
|
|
26
40
|
target = source + "/" + akg_kernel_mate_str + "/" + kernel_name
|
|
27
41
|
source = source + "/" + "kernel_meta/" + kernel_name
|
|
28
|
-
if
|
|
29
|
-
|
|
42
|
+
if source == target:
|
|
43
|
+
return True
|
|
44
|
+
akg_kernel_mate_str = os.path.abspath(akg_kernel_mate_str)
|
|
45
|
+
create_directory(akg_kernel_mate_str)
|
|
30
46
|
for postfix in postfixs:
|
|
31
47
|
if os.path.exists(source + postfix):
|
|
32
48
|
try:
|
|
33
49
|
shutil.move(source + postfix, target + postfix)
|
|
50
|
+
if postfix == ".json" and workspace_dict is not None:
|
|
51
|
+
set_workspace_for_json(target + postfix, workspace_dict)
|
|
34
52
|
except IOError as e:
|
|
35
53
|
logging.error("Unable to move file. {}".format(e))
|
|
36
54
|
except Exception as e:
|
|
@@ -152,7 +170,7 @@ def build_npu_for_akg(kernel_name,
|
|
|
152
170
|
generate_cce_code(mod, "cce", None)
|
|
153
171
|
|
|
154
172
|
|
|
155
|
-
def build_tbe_codegen(kernel_name, stmt_json, arg_json, ascend_type=None
|
|
173
|
+
def build_tbe_codegen(kernel_name, stmt_json, arg_json, attr, ascend_type=None):
|
|
156
174
|
import sys
|
|
157
175
|
copy_modules = sys.modules.copy()
|
|
158
176
|
clean_env()
|
|
@@ -186,6 +204,9 @@ def build_tbe_codegen(kernel_name, stmt_json, arg_json, ascend_type=None, is_dyn
|
|
|
186
204
|
arg_list = []
|
|
187
205
|
for buff in arg_json:
|
|
188
206
|
arg_list.append(tbe.tvm.ir.load_json(buff))
|
|
207
|
+
|
|
208
|
+
is_dynamic = attr.get("dynamic", False)
|
|
209
|
+
workspace_dict = attr.get("workspace", None)
|
|
189
210
|
with AscendPassContext(config=cfg):
|
|
190
211
|
build_npu_for_akg(kernel_name,
|
|
191
212
|
stmt,
|
|
@@ -193,6 +214,6 @@ def build_tbe_codegen(kernel_name, stmt_json, arg_json, ascend_type=None, is_dyn
|
|
|
193
214
|
is_dynamic=is_dynamic,
|
|
194
215
|
cfg=cfg)
|
|
195
216
|
postfixs = [".o", ".cce", ".json"]
|
|
196
|
-
is_success = copy_to_akg_kernel_meta(kernel_name, postfixs)
|
|
217
|
+
is_success = copy_to_akg_kernel_meta(kernel_name, postfixs, workspace_dict)
|
|
197
218
|
sys.modules = copy_modules
|
|
198
219
|
return is_success
|
mindspore/_akg/akg/utils/util.py
CHANGED
|
@@ -19,6 +19,7 @@ import os
|
|
|
19
19
|
import json
|
|
20
20
|
import types
|
|
21
21
|
import akg.tvm
|
|
22
|
+
from akg.utils.format_transform import get_shape
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
def parse_int_const(value):
|
|
@@ -29,6 +30,35 @@ def parse_int_const(value):
|
|
|
29
30
|
return None
|
|
30
31
|
|
|
31
32
|
|
|
33
|
+
def parse_workspace_map(attrs):
|
|
34
|
+
if not isinstance(attrs, akg.tvm.container.Map):
|
|
35
|
+
return None
|
|
36
|
+
if "workspace" not in attrs:
|
|
37
|
+
return None
|
|
38
|
+
|
|
39
|
+
workspace_map = attrs["workspace"]
|
|
40
|
+
if not isinstance(workspace_map, akg.tvm.container.Map):
|
|
41
|
+
return None
|
|
42
|
+
if "num" not in workspace_map or "size" not in workspace_map:
|
|
43
|
+
return None
|
|
44
|
+
|
|
45
|
+
worksapce_num = parse_int_const(workspace_map["num"])
|
|
46
|
+
if not isinstance(workspace_map["size"], akg.tvm.container.Array):
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
workspace_size = []
|
|
50
|
+
tt = get_shape(workspace_map["size"])
|
|
51
|
+
for item in tt:
|
|
52
|
+
workspace_size.append(parse_int_const(item))
|
|
53
|
+
if len(workspace_size) != worksapce_num:
|
|
54
|
+
return None
|
|
55
|
+
|
|
56
|
+
workspace_dict = {
|
|
57
|
+
"num": worksapce_num,
|
|
58
|
+
"size": workspace_size
|
|
59
|
+
}
|
|
60
|
+
return workspace_dict
|
|
61
|
+
|
|
32
62
|
def parse_workspace(workspace):
|
|
33
63
|
if not isinstance(workspace, akg.tvm.container.Map):
|
|
34
64
|
return None
|
|
@@ -63,3 +93,11 @@ def write_code(js_dict, fname):
|
|
|
63
93
|
with os.fdopen(os.open(fname, os.O_WRONLY | os.O_CREAT, 0o400), 'w') as f:
|
|
64
94
|
json.dump(js_dict, f, sort_keys=True, indent=4, separators=(',', ':'))
|
|
65
95
|
|
|
96
|
+
def get_ascend_type(desc):
|
|
97
|
+
if "target_info" not in desc.keys():
|
|
98
|
+
return None
|
|
99
|
+
|
|
100
|
+
target_info_type = desc["target_info"]
|
|
101
|
+
if target_info_type.get("arch"):
|
|
102
|
+
return target_info_type.get("arch")
|
|
103
|
+
return None
|
|
Binary file
|
|
Binary file
|
mindspore/_checkparam.py
CHANGED
|
@@ -720,9 +720,9 @@ def check_value_type(arg_name, arg_value, valid_types, prim_name=None):
|
|
|
720
720
|
type_names = [t.__name__ if hasattr(t, '__name__') else str(t) for t in valid_types]
|
|
721
721
|
num_types = len(valid_types)
|
|
722
722
|
msg_prefix = f"For '{prim_name}', the" if prim_name else "The"
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
723
|
+
raise TypeError(f'{msg_prefix} type of \'{arg_name}\' should be {"one of " if num_types > 1 else ""}' \
|
|
724
|
+
f'\'{type_names if num_types > 1 else type_names[0]}\', ' \
|
|
725
|
+
f'but got type \'{type(arg_value).__name__}\'.')
|
|
726
726
|
|
|
727
727
|
# Notice: bool is subclass of int, so `check_value_type('x', True, [int])` will check fail, and
|
|
728
728
|
# `check_value_type('x', True, [bool, int])` will check pass
|