From a7b57fb48c359fba2011fef8bf2f358b0799f26f Mon Sep 17 00:00:00 2001 From: lcw Date: Tue, 4 Mar 2025 16:08:59 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90bugfix=E3=80=91poc=E5=8F=8D=E5=90=88ma?= =?UTF-8?q?ster=20ut=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mindspore/debugger/precision_debugger.py | 1 - .../mindspore/dump/cell_dump_process.py | 583 ------------------ .../mindspore/dump/dump_tool_factory.py | 5 +- .../mindspore/dump/graph_mode_cell_dump.py | 75 --- .../pytorch/functional/data_processor.py | 0 .../debugger/test_graph_cell_dump.py | 309 ---------- .../pytorch_ut/compare/test_acc_compare.py | 267 -------- .../config_checking/test_config_checking.py | 107 ---- .../pytorch_ut/functional/test_dump_module.py | 15 - .../builder/test_graph_builder.py | 99 --- .../builder/test_msprobe_adapter.py | 104 ---- .../compare/test_graph_comparator.py | 143 ----- .../compare/test_mode_adapter.py | 99 --- .../visualization/graph/test_base_node.py | 76 --- .../visualization/graph/test_graph.py | 102 --- .../visualization/graph/test_node_colors.py | 67 -- .../visualization/graph/test_node_op.py | 28 - .../pytorch_ut/visualization/mapping.yaml | 2 - .../visualization/test_mapping_config.py | 52 -- .../pytorch_ut/visualization/test_utils.py | 27 - 20 files changed, 2 insertions(+), 2159 deletions(-) delete mode 100644 debug/accuracy_tools/msprobe/mindspore/dump/cell_dump_process.py delete mode 100644 debug/accuracy_tools/msprobe/mindspore/dump/graph_mode_cell_dump.py delete mode 100644 debug/accuracy_tools/msprobe/pytorch/functional/data_processor.py delete mode 100644 debug/accuracy_tools/msprobe/test/mindspore_ut/debugger/test_graph_cell_dump.py delete mode 100644 debug/accuracy_tools/msprobe/test/pytorch_ut/compare/test_acc_compare.py delete mode 100644 debug/accuracy_tools/msprobe/test/pytorch_ut/config_checking/test_config_checking.py delete mode 100644 debug/accuracy_tools/msprobe/test/pytorch_ut/functional/test_dump_module.py delete mode 100644 debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/builder/test_graph_builder.py delete mode 100644 debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/builder/test_msprobe_adapter.py delete mode 100644 debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/compare/test_graph_comparator.py delete mode 100644 debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/compare/test_mode_adapter.py delete mode 100644 debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/graph/test_base_node.py delete mode 100644 debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/graph/test_graph.py delete mode 100644 debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/graph/test_node_colors.py delete mode 100644 debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/graph/test_node_op.py delete mode 100644 debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/mapping.yaml delete mode 100644 debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/test_mapping_config.py delete mode 100644 debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/test_utils.py diff --git a/debug/accuracy_tools/msprobe/mindspore/debugger/precision_debugger.py b/debug/accuracy_tools/msprobe/mindspore/debugger/precision_debugger.py index a7082d3e56..fe1eac2dff 100644 --- a/debug/accuracy_tools/msprobe/mindspore/debugger/precision_debugger.py +++ b/debug/accuracy_tools/msprobe/mindspore/debugger/precision_debugger.py @@ -34,7 +34,6 @@ from msprobe.mindspore.ms_config import parse_json_config from msprobe.mindspore.runtime import Runtime from msprobe.mindspore.service import Service from msprobe.mindspore.task_handler_factory import TaskHandlerFactory -from msprobe.mindspore.dump.graph_mode_cell_dump import GraphModeCellDump try: from msprobe.lib import _msprobe_c diff --git a/debug/accuracy_tools/msprobe/mindspore/dump/cell_dump_process.py b/debug/accuracy_tools/msprobe/mindspore/dump/cell_dump_process.py deleted file mode 100644 index eea75d7894..0000000000 --- a/debug/accuracy_tools/msprobe/mindspore/dump/cell_dump_process.py +++ /dev/null @@ -1,583 +0,0 @@ -# Copyright (c) 2025-2025, Huawei Technologies Co., Ltd. -# All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import os -import time -import re -import json -import atexit -from multiprocessing import Pool - -import numpy as np -import mindspore as ms -from mindspore import nn, ops - -from msprobe.mindspore.common.log import logger -from msprobe.core.common.const import Const as CoreConst -from msprobe.core.common.file_utils import load_npy, save_json, remove_path, load_yaml -from msprobe.core.common.const import FileCheckConst - - -CONSTRUCT_FILE_NAME = "construct.json" -DEFAULT_RANK_DIR = "rank0" -KEY_LAYERS = "layers" -construct = {} -cell_list = [] -KEY_SIDE_EFFECT = "side_effect_io" -KEY_TOPLAYER = "TopLayer" -KEY_FORWARD = CoreConst.FORWARD -KEY_BACKWARD = CoreConst.BACKWARD -KEY_INPUT = CoreConst.INPUT -KEY_OUTPUT = CoreConst.OUTPUT -td = ops.TensorDump() -td_in = ops.TensorDump("in") -td.add_prim_attr(KEY_SIDE_EFFECT, False) -td_in.add_prim_attr(KEY_SIDE_EFFECT, False) -np_ms_dtype_dict = { - "bool": ms.bool_, - "int8": ms.int8, - "byte": ms.byte, - "int16": ms.int16, - "short": ms.short, - "int32": ms.int32, - "intc": ms.intc, - "int64": ms.int64, - "intp": ms.intp, - "uint8": ms.uint8, - "ubyte": ms.ubyte, - "uint16": ms.uint16, - "ushort": ms.ushort, - "uint32": ms.uint32, - "uintc": ms.uintc, - "uint64": ms.uint64, - "uintp": ms.uintp, - "float16": ms.float16, - "half": ms.half, - "float32": ms.float32, - "single": ms.single, - "float64": ms.float64, - "double": ms.double, - "bfloat16": ms.bfloat16, - "complex64": ms.complex64, - "complex128": ms.complex128 -} - - -def gen_file_path(dump_path, cell_prefix, suffix, io_type, index): - step_path = os.path.join(dump_path, "{step}") - rank_path = os.path.join(step_path, "{rank}") - data_path = os.path.join(rank_path, CoreConst.DUMP_TENSOR_DATA) - file_name = CoreConst.SEP.join([cell_prefix, suffix, io_type, str(index)]) - return os.path.join(data_path, file_name) - - -def partial_func(func, dump_path, cell_prefix, index, io_type): - def newfunc(*args, **kwargs): - return func(dump_path, cell_prefix, index, io_type, *args, **kwargs) - return newfunc - - -def clip_gradient(dump_path, cell_prefix, index, io_type, dx): - if io_type == KEY_OUTPUT: - temp = td(gen_file_path(dump_path, cell_prefix, KEY_BACKWARD, io_type, index), dx) - dx = ops.depend(dx, temp) - if io_type == KEY_INPUT: - temp = td_in(gen_file_path(dump_path, cell_prefix, KEY_BACKWARD, io_type, index), dx) - dx = ops.depend(dx, temp) - return dx - - -def need_tensordump_in(cell_obj, attr): - return hasattr(cell_obj, attr) and getattr(cell_obj, attr) == "in" - - -def cell_construct_wrapper(func, self): - def new_construct(self, *args, **kwargs): - new_args = [] - out_list = [] - - index = 0 - item = None - # The inputs of the cell. - for index, item in enumerate(args): - if self.data_mode == "backward" or self.data_mode == "all": - if ops.is_tensor(item): - item = self.output_clips[index](item) - if self.data_mode == "forward" or self.data_mode == "all": - if ops.is_tensor(item): - if need_tensordump_in(self, 'input_dump_mode'): - temp = td_in( - gen_file_path(self.dump_path, self.cell_prefix, KEY_FORWARD, KEY_INPUT, index), - item - ) - else: - temp = td( - gen_file_path(self.dump_path, self.cell_prefix, KEY_FORWARD, KEY_INPUT, index), - item - ) - item = ops.depend(item, temp) - new_args.append(item) - - out = func(*new_args, **kwargs) - - # The outputs of the cell. - if isinstance(out, tuple): - for index, item in enumerate(out): - if self.data_mode == "backward" or self.data_mode == "all": - if ops.is_tensor(item): - item = self.input_clips[index](item) - if self.data_mode == "forward" or self.data_mode == "all": - if ops.is_tensor(item): - if need_tensordump_in(self, 'output_dump_mode'): - temp = td_in( - gen_file_path(self.dump_path, self.cell_prefix, KEY_FORWARD, KEY_OUTPUT, index), - item - ) - else: - temp = td( - gen_file_path(self.dump_path, self.cell_prefix, KEY_FORWARD, KEY_OUTPUT, index), - item - ) - item = ops.depend(item, temp) - out_list.append(item) - else: - out_list.append(item) - out_list = tuple(out_list) - return out_list - else: - if self.data_mode == "backward" or self.data_mode == "all": - out = self.input_clips[0](out) - if self.data_mode == "forward" or self.data_mode == "all": - if ops.is_tensor(out): - if need_tensordump_in(self, 'output_dump_mode'): - temp = td_in( - gen_file_path(self.dump_path, self.cell_prefix, KEY_FORWARD, KEY_OUTPUT, 0), - out - ) - else: - temp = td( - gen_file_path(self.dump_path, self.cell_prefix, KEY_FORWARD, KEY_OUTPUT, 0), - out - ) - out = ops.depend(out, temp) - return out - - return new_construct.__get__(self, type(self)) - - -# 获取目录下所有文件名并根据TensorDump落盘自增id从小到大排序 -def sort_filenames(path): - filenames = os.listdir(path) - id_pattern = re.compile(rf'{CoreConst.REPLACEMENT_CHARACTER}(\d+){CoreConst.NUMPY_SUFFIX}$') - filenames.sort(key=lambda x: int(id_pattern.findall(x)[0])) - return filenames - - -# 删除重复dump的文件:自定义文件名相同,并且数据相同 -def del_same_file(path, filenames): - result_list = [] - seen_prefixes = {} - for current_filename in filenames: - parts = current_filename.rsplit(CoreConst.REPLACEMENT_CHARACTER, 1) - prefix = parts[0] - if prefix not in seen_prefixes: - result_list.append(current_filename) - seen_prefixes[prefix] = current_filename - else: - current_file_path = os.path.join(path, current_filename) - current_file = load_npy(current_file_path) - prev_filename = seen_prefixes[prefix] - prev_file_path = os.path.join(path, prev_filename) - prev_file = load_npy(prev_file_path) - if np.array_equal(current_file, prev_file): - remove_path(current_file_path) - logger.warning(f"{current_file_path} is deleted!") - else: - result_list.append(current_filename) - return result_list - - -def rename_filename(path): - filenames = sort_filenames(path) - filenames = del_same_file(path, filenames) - - filename_dict = {} - for filename in filenames: - name_field = filename.rsplit(CoreConst.REPLACEMENT_CHARACTER, 1)[0] - - if name_field in filename_dict: - filename_dict[name_field] += 1 - else: - filename_dict[name_field] = 0 - - cell_index = filename_dict[name_field] - - # 修改文件名,增加重复调用Cell的序号 - if CoreConst.FORWARD_PATTERN in filename: - #Format: Cell.{cell_name}.{class_name}.{forward/backward}.{number}.{input/output}.{index}_{dtype}_{id}.npy - newFileName = filename.replace(CoreConst.FORWARD_PATTERN, CoreConst.FORWARD_PATTERN + str(cell_index) + CoreConst.SEP) - if CoreConst.BACKWARD_PATTERN in filename: - newFileName = filename.replace(CoreConst.BACKWARD_PATTERN, CoreConst.BACKWARD_PATTERN + str(cell_index) + CoreConst.SEP) - os.rename(os.path.join(path, filename), os.path.join(path, newFileName)) - logger.info(f"==========The rename_filename phase is Finished!==========") - - -# Extract the field between the first "." and the third to last ".", i.e. {cell_name} -def get_cell_name(str): - parts = str.split(CoreConst.SEP) - if len(parts) < 4: - return None - start_index = 1 - end_index = len(parts) - 3 - return CoreConst.SEP.join(parts[start_index:end_index]) - - -# Extract the field between the last "." and the second to last ".", i.e. {data_made} -def get_data_mode(str): - last_dot_index = str.rfind(CoreConst.SEP) - second_last_dot_index = str.rfind(CoreConst.SEP, 0, last_dot_index) - data_mode = str[second_last_dot_index + 1:last_dot_index] - return data_mode - - -# 判断二者之间是否存在父子关系 -def check_relation(cell_name, parent_cell_name): - layers_pattern = rf"{CoreConst.SEP}{KEY_LAYERS}{CoreConst.SEP}\d+$" - last_dot_index = cell_name.rfind(CoreConst.SEP) - if last_dot_index != -1: - # 如果cell_name最后一个'.'之前的字段等于parent_cell_name,则判定存在父子关系 - sub_cell_name = cell_name[:last_dot_index] - if sub_cell_name == parent_cell_name: - return True - elif re.search(layers_pattern, cell_name): - # 如果cell_name以".layer.{layer_id}"结尾,且去掉该字段后等于parent_cell_name,则判定存在父子关系 - sub_cell_name = re.sub(layers_pattern, '', cell_name) - if sub_cell_name == parent_cell_name: - return True - return False - - -def get_construct(cell_list_input): - for cell in cell_list_input: - cell_name = get_cell_name(cell) - cell_data_mode = get_data_mode(cell) - found_flag = False - for parent_cell in cell_list_input: - parent_cell_name = get_cell_name(parent_cell) - parent_data_mode = get_data_mode(parent_cell) - has_relation = check_relation(cell_name, parent_cell_name) - if has_relation and parent_data_mode == cell_data_mode: - construct.update({cell: parent_cell}) - found_flag = True - break - if not found_flag: - construct.update({cell: None}) - - -def generate_construct(path): - global construct - filenames = sort_filenames(path) - - # 提取文件名中Cell.{cell_name}.{class_name}.{data_mode}.{重复调用此cell的序号}字段,并存入cell_list - for filename in filenames: - point_position = 3 - mid_field = filename.rsplit(CoreConst.SEP, point_position)[0] - if KEY_INPUT in filename: - if mid_field in cell_list: - cell_list.remove(mid_field) - cell_list.append(mid_field) - else: - if mid_field not in cell_list: - index = filenames.index(filename) - output_field = mid_field + KEY_OUTPUT - find_flag = False - for filename_other in cell_list[index + 1:]: - if output_field in filename_other: - find_flag = True - if find_flag is False: - cell_list.append(mid_field) - - get_construct(cell_list) - - # 生成JSON文件 - rank_dir = os.path.dirname(path) - json_path = os.path.join(rank_dir, CONSTRUCT_FILE_NAME) - save_json(json_path, construct, indent=1) - - # 清空'construct'继续处理下一个路径下的数据 - construct = {} - logger.info(f"Construct data saved to {json_path}") - - -def process_file(file_path): - try: - # 读取.npy文件内容 - npy_content = load_npy(file_path) - logger.info(f"Loaded {file_path}: shape is {npy_content.shape}, dtype is {npy_content.dtype}") - - # 文件名举例:Cell.network._backbone.loss.CrossEntropyLoss.forward.0.input.0_float32_165.npy - parts = os.path.basename(file_path).split(CoreConst.SEP) - data_dtype = "" - # 获取0_float32_165或者0_in_float32_165中的float32 - data_dtype_list = parts[-2].split('_') - if len(data_dtype_list) > 1: - data_dtype = data_dtype_list[-2] - # op_name是Cell.network._backbone.loss.CrossEntropyLoss.forward.0 - op_name = CoreConst.SEP.join(parts[:-3]) - ms_dtype = np_ms_dtype_dict.get(data_dtype) - if ms_dtype is None: - logger.warning(f"Get dtype None from file {file_path}") - - #修改落盘文件名字,去掉TensorDump自带的数据类型和自增id字段 - data_file_name = os.path.basename(file_path) - data_file_dir = os.path.dirname(file_path) - parts = data_file_name.split(CoreConst.SEP) - if len(parts) >= 2: - param_index = parts[-2].split(CoreConst.REPLACEMENT_CHARACTER)[0] - pre_parts = CoreConst.SEP.join(parts[:-2]) - new_file_name = pre_parts + CoreConst.SEP + param_index + CoreConst.NUMPY_SUFFIX - os.rename(os.path.join(data_file_dir, data_file_name), os.path.join(data_file_dir, new_file_name)) - logger.info(f"{data_file_name} is renamed to {new_file_name}") - else: - logger.warning(f"Failed to rename {data_file_name}.") - new_file_name = data_file_name - - tensor_json = { - CoreConst.TYPE: 'mindspore.Tensor', - CoreConst.DTYPE: str(ms_dtype), - CoreConst.SHAPE: list(npy_content.shape), - CoreConst.MAX: npy_content.max().item(), - CoreConst.MIN: npy_content.min().item(), - CoreConst.MEAN: npy_content.mean().item(), - CoreConst.NORM: np.linalg.norm(npy_content).item(), - CoreConst.DATA_NAME: new_file_name - } - - # 根据文件名的最后一个部分(输入或输出)确定是添加到input_args还是output - if parts[-3] == KEY_INPUT: - return op_name, CoreConst.INPUT_ARGS, tensor_json - elif parts[-3] == KEY_OUTPUT: - return op_name, KEY_OUTPUT, tensor_json - else: - return None, None, None - - except Exception as e: - logger.error(f"Error reading {file_path}: {e}") - return None, None, None - - -def custom_sort(item, key_to_index): - key = item[0] - return key_to_index.get(key, float('inf')) - - -def generate_dump_info(path): - if not os.path.exists(path): - logger.error("The provided path does not exist.") - return - - dump_data = {"task": "tensor", "level": "L0", "dump_data_dir": path, "data": {}} - - with Pool(processes=10) as pool: - file_paths = [] - for root, _, files in os.walk(path): - for file in files: - if file.endswith(FileCheckConst.NUMPY_SUFFIX): - file_paths.append((os.path.join(root, file),)) - file_paths.sort() - results = pool.starmap(process_file, file_paths) - - # 收集结果 - for op_name, key, tensor_json in results: - if op_name: - if op_name not in dump_data.get(CoreConst.DATA, {}): - dump_data.get(CoreConst.DATA, {})[op_name] = {CoreConst.INPUT_ARGS: [], - CoreConst.INPUT_KWARGS: {}, - KEY_OUTPUT: []} - if key not in dump_data.get(CoreConst.DATA, {}).get(op_name, {}): - dump_data.get(CoreConst.DATA, {}).get(op_name, {})[key] = [] - dump_data.get(CoreConst.DATA, {}).get(op_name, {}).get(key, []).append(tensor_json) - - # 根据cell_list排序 - data_dict = dump_data.get(CoreConst.DATA, {}) - key_to_index = {key: index for index, key in enumerate(cell_list)} - sorted_data_dict = dict(sorted(data_dict.items(), key=lambda item: custom_sort(item, key_to_index))) - dump_data[CoreConst.DATA] = sorted_data_dict - - # 将数据写入dump.json - json_path = os.path.join(os.path.dirname(path), 'dump.json') - save_json(json_path, dump_data, indent=1) - - logger.info(f"Dump data saved to {json_path}") - - -def generate_stack_info(path): - if not os.path.exists(path): - logger.error("The provided path does not exist.") - return - - stack_data = {} - file_paths = [] - # 传入的path为工具生成的./dump_tensor_data,内容为npy文件 - for root, _, files in os.walk(path): - for file in files: - if file.endswith(FileCheckConst.NUMPY_SUFFIX): - file_paths.append(os.path.join(root, file)) - file_paths.sort() - for file_path in file_paths: - # 文件名举例:Cell.network._backbone.loss.CrossEntropyLoss.forward.0.input.0_float32_165.npy - parts = os.path.basename(file_path).split(CoreConst.SEP) - # op_name是Cell.network._backbone.loss.CrossEntropyLoss.forward.0 - op_name = CoreConst.SEP.join(parts[:-3]) - stack_data.update({op_name: []}) - - # 将数据写入stack.json - json_path = os.path.join(os.path.dirname(path), 'stack.json') - save_json(json_path, stack_data, indent=1) - - logger.info(f"Stack data saved to {json_path}") - - -def is_download_finished(directory, interval=3): - """ - 判断指定目录在一段时间后是否有数据被下载完成 - :param directory: 指定目录的路径 - :param interval: 检查的时间间隔(秒),默认为 3 秒 - :return: 如有数据被下载完成返回 True,否则返回 False - """ - # 检查目录是否存在 - if not os.path.exists(directory): - logger.warning(f"The specified directory {directory} does not exist.") - return False - initial_modification_time = os.path.getmtime(directory) - time.sleep(interval) - current_modification_time = os.path.getmtime(directory) - # 比较初始和当前修改时间 - if current_modification_time > initial_modification_time: - return False - else: - return True - - -def process(dump_path): - rank_id = os.environ.get('RANK_ID') - rank_dir = DEFAULT_RANK_DIR - if rank_id is not None: - rank_dir = CoreConst.RANK + str(rank_id) - - step_dir_list = os.listdir(dump_path) - for step_dir in step_dir_list: - step_path = os.path.join(dump_path, step_dir) - rank_path = os.path.join(step_path, rank_dir) - npy_path = os.path.join(rank_path, CoreConst.DUMP_TENSOR_DATA) - while True: - is_finished = is_download_finished(npy_path) - if not is_finished: - logger.info(f"There is data being downloaded in the specified directory, continue checking...") - else: - logger.info(f"There is no data being downloaded in the specified directory, Stop checking.") - break - logger.info(f"==========Start processing data that has already been stored on the disk!==========") - rename_filename(npy_path) - generate_construct(npy_path) - generate_dump_info(npy_path) - generate_stack_info(npy_path) - logger.info(f"==========JSON file generation completed!==========") - - -def get_yaml_keys(yaml_data): - keys = [] - for key, _ in yaml_data.items(): - keys.append(key) - return keys - - -def get_tensordump_mode(input_str): - left_index = input_str.find('(') - right_index = input_str.find(')') - - # 提取括号内的字符串 - if left_index != -1 and right_index != -1: - inner_str = input_str[left_index + 1:right_index] - # 分割字符串得到元素列表 - elements = inner_str.split(',') - if len(elements) >= 2: - # 去除元素前后的空格 - first_element = elements[0].strip() - second_element = elements[1].strip() - return first_element, second_element - return None, None - - -def set_tensordump_mode(cell, input_str): - first_str, second_str = get_tensordump_mode(input_str) - if first_str and second_str: - cell.input_dump_mode = first_str - cell.output_dump_mode = second_str - - -def start(net=None, dump_path="./", data_mode=CoreConst.ALL, td_config_path=''): - if net is None: - return - - if td_config_path == "": - yaml_data = {} - else: - yaml_data = load_yaml(td_config_path) - first_layer_key = get_yaml_keys(yaml_data) - - black_list = ["grad_reducer", ""] - for name, cell in net.cells_and_names(): - class_name = cell.__class__.__name__ - # 跳过黑名单cell - if name in black_list: - logger.info(f"Cell {name}.{class_name} is skipped!") - continue - # 跳过框架内部的cell - if class_name.startswith(CoreConst.REPLACEMENT_CHARACTER): - logger.info(f"Cell {name}.{class_name} is skipped!") - continue - else: - #Format: Cell.{cell_name}.{class_name} - cell.cell_prefix = CoreConst.SEP.join([CoreConst.CELL, name, cell.__class__.__name__]) - - # 根据yaml配置文件设置cell的TensorDump模式 - if class_name in first_layer_key: - layer_data = yaml_data.get(class_name) - if layer_data: - for child_name, child_cell in cell.cells_and_names(): - if child_name in layer_data: - set_tensordump_mode(child_cell, layer_data[child_name]) - top_layer_data = yaml_data.get(KEY_TOPLAYER) - if top_layer_data and name in top_layer_data: - set_tensordump_mode(cell, top_layer_data[name]) - - # 替换construct函数 - cell.construct = cell_construct_wrapper(cell.construct, cell) - logger.info(f"Cell {name}: construct function is wrapped!") - cell.dump_path = dump_path - cell.data_mode = data_mode - cell.input_clips = [] - cell.output_clips = [] - # It is assumed that each cell has a maximum of 50 outputs and 50 inputs. - for i in range(50): - cell.input_clips.append( - ops.InsertGradientOf(partial_func(clip_gradient, cell.dump_path, cell.cell_prefix, i, KEY_INPUT)) - ) - cell.output_clips.append( - ops.InsertGradientOf(partial_func(clip_gradient, cell.dump_path, cell.cell_prefix, i, KEY_OUTPUT)) - ) - - logger.info(f"==========The cell_dump_process_start phase is Finished!==========") - atexit.register(process, dump_path=dump_path) diff --git a/debug/accuracy_tools/msprobe/mindspore/dump/dump_tool_factory.py b/debug/accuracy_tools/msprobe/mindspore/dump/dump_tool_factory.py index c0933d20aa..7618952202 100644 --- a/debug/accuracy_tools/msprobe/mindspore/dump/dump_tool_factory.py +++ b/debug/accuracy_tools/msprobe/mindspore/dump/dump_tool_factory.py @@ -17,14 +17,13 @@ from msprobe.mindspore.common.const import Const from msprobe.mindspore.debugger.debugger_config import DebuggerConfig from msprobe.mindspore.dump.kernel_graph_dump import KernelGraphDump from msprobe.mindspore.dump.kernel_kbyk_dump import KernelKbykDump -from msprobe.mindspore.dump.graph_mode_cell_dump import GraphModeCellDump class DumpToolFactory: tools = { Const.CELL: { - Const.GRAPH_KBYK_MODE: GraphModeCellDump, - Const.GRAPH_GE_MODE: GraphModeCellDump, + Const.GRAPH_KBYK_MODE: None, + Const.GRAPH_GE_MODE: None, Const.PYNATIVE_MODE: None }, Const.API: { diff --git a/debug/accuracy_tools/msprobe/mindspore/dump/graph_mode_cell_dump.py b/debug/accuracy_tools/msprobe/mindspore/dump/graph_mode_cell_dump.py deleted file mode 100644 index 3d476a4f25..0000000000 --- a/debug/accuracy_tools/msprobe/mindspore/dump/graph_mode_cell_dump.py +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright (c) 2025-2025, Huawei Technologies Co., Ltd. -# All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import os -from msprobe.mindspore.common.log import logger -from msprobe.mindspore.debugger.debugger_config import DebuggerConfig -import mindspore as ms -from mindspore._c_expression import _tensordump_set_step -from mindspore.ops.primitive import _run_op -from mindspore import hal, ops -import msprobe.mindspore.dump.cell_dump_process as cellDumper -from msprobe.mindspore.common.const import Const - - -class GraphModeCellDump: - def __init__(self, config: DebuggerConfig, model): - self.net = model - self.white_list = [] - self.black_list = [] - self.dump_path = config.dump_path if config.dump_path else "./" - self.rank = config.rank - self.step = config.step - self.scope = config.scope - self.list = config.list - self.data_mode = config.data_mode - self.file_format = config.file_format - self.td_config_path = config.td_config_path - self.check_config() - self.set_step() - - @staticmethod - def step(): - hal.synchronize() - temp_tensor = ms.Tensor([1], dtype=ms.float32) - step_flag = "" - _run_op(ops.TensorDump(), "TensorDump", (step_flag, temp_tensor)) - ops.tensordump(step_flag, temp_tensor) - - def check_config(self): - if self.rank != []: - raise Exception("In graph mode, cell dump does not currently support specifying rank.") - if self.scope != []: - raise Exception("In graph mode, cell dump does not currently support specifying scope.") - if self.list != []: - raise Exception("In graph mode, cell dump does not currently support specifying list.") - if len(self.data_mode) != 1 or self.data_mode[0] not in Const.GRAPH_CELL_DUMP_DATA_MODE_LIST: - raise Exception("In graph mode and cell dump, data_mode must be one of all, forword, backword.") - if self.file_format != []: - logger.warning("In graph mode, cell dump does not currently support specifying file_format. The file will be stored in npy format.") - if not self.net: - raise Exception("The model is empty and cell dump is not enabled.") - return True - - def set_step(self): - _tensordump_set_step(self.step) - - def handle(self): - os.environ['MS_JIT_MODULES'] = 'msprobe' - cellDumper.start( - net=self.net, - dump_path=self.dump_path, - data_mode=self.data_mode[0], - td_config_path=self.td_config_path - ) diff --git a/debug/accuracy_tools/msprobe/pytorch/functional/data_processor.py b/debug/accuracy_tools/msprobe/pytorch/functional/data_processor.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/debug/accuracy_tools/msprobe/test/mindspore_ut/debugger/test_graph_cell_dump.py b/debug/accuracy_tools/msprobe/test/mindspore_ut/debugger/test_graph_cell_dump.py deleted file mode 100644 index b111e64437..0000000000 --- a/debug/accuracy_tools/msprobe/test/mindspore_ut/debugger/test_graph_cell_dump.py +++ /dev/null @@ -1,309 +0,0 @@ -# Copyright (c) 2025-2025, Huawei Technologies Co., Ltd. -# All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import os -import re -import unittest -from unittest.mock import MagicMock, patch - -import mindspore as ms -from mindspore import ops - -from msprobe.core.common.const import Const as CoreConst -from msprobe.mindspore.dump.cell_dump_process import generate_file_path -from msprobe.mindspore.dump.cell_dump_process import partial_func, clip_gradient -from msprobe.mindspore.dump.cell_dump_process import cell_construct_wrapper -from msprobe.mindspore.dump.cell_dump_process import rename_filename, sort_filenames, del_same_file -from msprobe.mindspore.dump.cell_dump_process import check_relation - - -class TestGenerateFilePath(unittest.TestCase): - def setUp(self): - self.dump_path = "/path" - self.cell_prefix = "Cell.network._backbone.LlamaForCausalLM" - self.suffix = "forward" - self.io_type = "input" - self.index = 0 - - def test_generate_file_path(self): - expected_path = os.path.join( - self.dump_path, - "{step}", - "{rank}", - CoreConst.DUMP_TENSOR_DATA, - CoreConst.SEP.join([self.cell_prefix, self.suffix, self.io_type, str(self.index)]) - ) - result = generate_file_path(self.dump_path, self.cell_prefix, self.suffix, self.io_type, self.index) - self.assertEqual(result, expected_path) - - -class TestPartialFunc(unittest.TestCase): - - @patch('msprobe.mindspore.dump.cell_dump_process.CoreConst') - @patch('msprobe.mindspore.dump.cell_dump_process.td') - @patch('msprobe.mindspore.dump.cell_dump_process.td_in') - @patch('msprobe.mindspore.dump.cell_dump_process.generate_file_path') - @patch('msprobe.mindspore.dump.cell_dump_process.ops.depend') - def test_clip_gradient_output(self, mock_depend, mock_generate_file_path, mock_td_in, mock_td, mock_CoreConst): - mock_CoreConst.OUTPUT = "output" - mock_CoreConst.BACKWARD = "backward" - mock_generate_file_path.return_value = "mock_path" - mock_td.return_value = "temp_tensor" - mock_depend.return_value = "dependent_tensor" - - result = clip_gradient("dump_path", "cell_prefix", 0, "output", "dx") - - mock_generate_file_path.assert_called_with("dump_path", "cell_prefix", "backward", "output", 0) - mock_td.assert_called_with("mock_path", "dx") - mock_depend.assert_called_with("dx", "temp_tensor") - self.assertEqual(result, "dependent_tensor") - - @patch('msprobe.mindspore.dump.cell_dump_process.CoreConst') - @patch('msprobe.mindspore.dump.cell_dump_process.td') - @patch('msprobe.mindspore.dump.cell_dump_process.td_in') - @patch('msprobe.mindspore.dump.cell_dump_process.generate_file_path') - @patch('msprobe.mindspore.dump.cell_dump_process.ops.depend') - def test_clip_gradient_input(self, mock_depend, mock_generate_file_path, mock_td_in, mock_td, mock_CoreConst): - mock_CoreConst.INPUT = "input" - mock_CoreConst.BACKWARD = "backward" - mock_generate_file_path.return_value = "mock_path" - mock_td_in.return_value = "temp_tensor" - mock_depend.return_value = "dependent_tensor" - - result = clip_gradient("dump_path", "cell_prefix", 0, "input", "dx") - - mock_generate_file_path.assert_called_with("dump_path", "cell_prefix", "backward", "input", 0) - mock_td_in.assert_called_with("mock_path", "dx") - mock_depend.assert_called_with("dx", "temp_tensor") - self.assertEqual(result, "dependent_tensor") - - def test_partial_func(self): - def mock_func(dump_path, cell_prefix, index, io_type, *args, **kwargs): - return dump_path, cell_prefix, index, io_type, args, kwargs - - new_func = partial_func(mock_func, "dump_path", "cell_prefix", 0, "io_type") - result = new_func("arg1", "arg2", kwarg1="value1") - - self.assertEqual(result, ("dump_path", "cell_prefix", 0, "io_type", ("arg1", "arg2"), {'kwarg1': 'value1'})) - - -class TestCellWrapperProcess(unittest.TestCase): - - @patch('msprobe.mindspore.dump.cell_dump_process.generate_file_path') - @patch('msprobe.mindspore.dump.cell_dump_process.td') - @patch('msprobe.mindspore.dump.cell_dump_process.td_in') - def test_cell_construct_wrapper(self, mock_td_in, mock_td, mock_generate_file_path): - # Mock the generate_file_path function - mock_generate_file_path.return_value = "mock_path" - - # Mock the TensorDump operations - mock_td.return_value = MagicMock() - mock_td_in.return_value = MagicMock() - - # Create a mock cell with necessary attributes - mock_cell = MagicMock() - mock_cell.data_mode = "all" - mock_cell.dump_path = "mock_dump_path" - mock_cell.cell_prefix = "mock_cell_prefix" - mock_cell.input_clips = [MagicMock() for _ in range(50)] - mock_cell.output_clips = [MagicMock() for _ in range(50)] - - # Define a mock function to wrap - def mock_func(*args, **kwargs): - return args - - # Wrap the mock function using cell_construct_wrapper - wrapped_func = cell_construct_wrapper(mock_func, mock_cell) - - # Create mock inputs - mock_input = ms.Tensor([1, 2, 3]) - mock_args = (mock_input,) - - # Call the wrapped function - result = wrapped_func(mock_cell, *mock_args) - - # Check if the result is as expected - self.assertEqual(result, mock_args) - - # Verify that the TensorDump operations were called - mock_td_in.assert_called() - mock_td.assert_called() - - @patch('msprobe.mindspore.dump.cell_dump_process.generate_file_path') - @patch('msprobe.mindspore.dump.cell_dump_process.td') - @patch('msprobe.mindspore.dump.cell_dump_process.td_in') - def test_cell_construct_wrapper_with_tuple_output(self, mock_td_in, mock_td, mock_generate_file_path): - # Mock the generate_file_path function - mock_generate_file_path.return_value = "mock_path" - - # Mock the TensorDump operations - mock_td.return_value = MagicMock() - mock_td_in.return_value = MagicMock() - - # Create a mock cell with necessary attributes - mock_cell = MagicMock() - mock_cell.data_mode = "all" - mock_cell.dump_path = "mock_dump_path" - mock_cell.cell_prefix = "mock_cell_prefix" - mock_cell.input_clips = [MagicMock() for _ in range(50)] - mock_cell.output_clips = [MagicMock() for _ in range(50)] - - # Define a mock function to wrap - def mock_func(*args, **kwargs): - return (args[0], args[0]) - - # Wrap the mock function using cell_construct_wrapper - wrapped_func = cell_construct_wrapper(mock_func, mock_cell) - - # Create mock inputs - mock_input = ms.Tensor([1, 2, 3]) - mock_args = (mock_input,) - - # Call the wrapped function - result = wrapped_func(mock_cell, *mock_args) - - # Check if the result is as expected - self.assertEqual(result, (mock_input, mock_input)) - - # Verify that the TensorDump operations were called - mock_td_in.assert_called() - mock_td.assert_called() - - -class TestSortFilenames(unittest.TestCase): - - @patch('os.listdir') - def test_sort_filenames(self, mock_listdir): - # Mock the list of filenames returned by os.listdir - mock_listdir.return_value = [ - 'Cell.network._backbone.model.LlamaModel.backward.0.input.0_float16_177.npy', - 'Cell.network._backbone.model.LlamaModel.forward.0.input.0_in_int32_1.npy', - 'Cell.network._backbone.model.LlamaModel.forward.0.output.10_float16_165.npy', - 'Cell.network._backbone.model.norm_out.LlamaRMSNorm.backward.0.input.0_float16_178.npy' - ] - - # Mock the CoreConst values - CoreConst.REPLACEMENT_CHARACTER = '_' - CoreConst.NUMPY_SUFFIX = '.npy' - - # Expected sorted filenames - expected_sorted_filenames = [ - 'Cell.network._backbone.model.LlamaModel.forward.0.input.0_in_int32_1.npy', - 'Cell.network._backbone.model.LlamaModel.forward.0.output.10_float16_165.npy', - 'Cell.network._backbone.model.LlamaModel.backward.0.input.0_float16_177.npy', - 'Cell.network._backbone.model.norm_out.LlamaRMSNorm.backward.0.input.0_float16_178.npy' - ] - - # Call the function - sorted_filenames = sort_filenames('/mock/path') - - # Assert the filenames are sorted correctly - self.assertEqual(sorted_filenames, expected_sorted_filenames) - - -class TestRenameFilename(unittest.TestCase): - - @patch('msprobe.mindspore.dump.cell_dump_process.sort_filenames') - @patch('msprobe.mindspore.dump.cell_dump_process.del_same_file') - @patch('msprobe.mindspore.dump.cell_dump_process.os.rename') - def test_rename_filename(self, mock_rename, mock_del_same_file, mock_sort_filenames): - # Mock the constants - CoreConst.REPLACEMENT_CHARACTER = '_' - CoreConst.FORWARD_PATTERN = '.forward.' - CoreConst.BACKWARD_PATTERN = '.backward.' - CoreConst.SEP = '.' - - # Mock the filenames - mock_sort_filenames.return_value = [ - "Cell.learning_rate.CosineWithWarmUpLR.forward.input.0_int32_101.npy", - "Cell.learning_rate.CosineWithWarmUpLR.forward.output.0_float32_102.npy", - "Cell.loss_scaling_manager.DynamicLossScaleUpdateCell.backward.input.0_float32_103.npy", - "Cell.loss_scaling_manager.DynamicLossScaleUpdateCell.backward.input.1_bool_104.npy", - "Cell.loss_scaling_manager.DynamicLossScaleUpdateCell.backward.output.1_bool_105.npy", - "Cell.learning_rate.CosineWithWarmUpLR.forward.input.0_int32_111.npy", - "Cell.learning_rate.CosineWithWarmUpLR.forward.output.0_float32_112.npy", - ] - mock_del_same_file.return_value = [mock_sort_filenames.return_value] - - # Call the function - rename_filename('/mock/path') - - # Check if os.rename was called with the correct arguments - mock_rename.assert_any_call( - '/mock/path/Cell.learning_rate.CosineWithWarmUpLR.forward.input.0_int32_101.npy', - '/mock/path/Cell_learning_rate_CosineWithWarmUpLR.forward.0.input_0_int32_101.npy' - ) - mock_rename.assert_any_call( - '/mock/path/Cell.learning_rate.CosineWithWarmUpLR.forward.output.0_float32_102.npy', - '/mock/path/Cell_learning_rate_CosineWithWarmUpLR.forward.0.output_0_float32_102.npy' - ) - mock_rename.assert_any_call( - '/mock/path/Cell.loss_scaling_manager.DynamicLossScaleUpdateCell.backward.input.0_float32_103.npy', - '/mock/path/Cell_loss_scaling_manager_DynamicLossScaleUpdateCell.backward.0.input_0_float32_103.npy' - ) - mock_rename.assert_any_call( - '/mock/path/Cell.loss_scaling_manager.DynamicLossScaleUpdateCell.backward.input.1_bool_104.npy', - '/mock/path/Cell_loss_scaling_manager_DynamicLossScaleUpdateCell.backward.0.input_1_bool_104.npy' - ) - mock_rename.assert_any_call( - '/mock/path/Cell.loss_scaling_manager.DynamicLossScaleUpdateCell.backward.output.1_bool_105.npy', - '/mock/path/Cell_loss_scaling_manager_DynamicLossScaleUpdateCell.backward.0.output_1_bool_105.npy' - ) - mock_rename.assert_any_call( - '/mock/path/Cell.learning_rate.CosineWithWarmUpLR.forward.input.0_int32_111.npy', - '/mock/path/Cell_learning_rate_CosineWithWarmUpLR.forward.1.input_0_int32_111.npy' - ) - mock_rename.assert_any_call( - '/mock/path/Cell.learning_rate.CosineWithWarmUpLR.forward.output.0_float32_112.npy', - '/mock/path/Cell_learning_rate_CosineWithWarmUpLR.forward.1.output_0_float32_112.npy' - ) - - # Mock the filenames - mock_sort_filenames.return_value = [] - mock_del_same_file.return_value = [] - - # Call the function - rename_filename('/mock/path') - - # Check if os.rename was not called - mock_rename.assert_not_called() - - -class TestCheckRelation(unittest.TestCase): - - def setUp(self): - CoreConst.SEP = '.' - global KEY_LAYERS - KEY_LAYERS = "layers" - - def test_direct_parent_child_relation(self): - self.assertTrue(check_relation("network._backbone", "network")) - self.assertTrue(check_relation("network._backbone.model", "network._backbone")) - - def test_no_relation(self): - self.assertFalse(check_relation("network._backbone", "network.loss")) - self.assertFalse(check_relation("network._backbone.model", "network.loss")) - - def test_layer_pattern_relation(self): - self.assertTrue(check_relation("network.model.layers.0", "network.model")) - self.assertTrue(check_relation("network._backbone.model.layers.1", "network._backbone.model")) - - def test_no_layer_pattern_relation(self): - self.assertFalse(check_relation("network.model.layers.0", "network.loss")) - self.assertFalse(check_relation("network._backbone.model.layers.1", "network._backbone.model.layers")) - - def test_edge_cases(self): - self.assertFalse(check_relation("", "network")) - self.assertFalse(check_relation("network.layer1", "")) - self.assertFalse(check_relation("", "")) diff --git a/debug/accuracy_tools/msprobe/test/pytorch_ut/compare/test_acc_compare.py b/debug/accuracy_tools/msprobe/test/pytorch_ut/compare/test_acc_compare.py deleted file mode 100644 index 288e259c0a..0000000000 --- a/debug/accuracy_tools/msprobe/test/pytorch_ut/compare/test_acc_compare.py +++ /dev/null @@ -1,267 +0,0 @@ -# coding=utf-8 -import unittest -import pandas as pd -from msprobe.pytorch.compare import acc_compare as compare - -npu_dict = {'op_name': ['Functional_conv2d_0_forward_input.0', 'Functional_conv2d_0_forward_input.1', - 'Functional_conv2d_0_forward_input.2', 'Functional_conv2d_0_forward_output'], - 'input_struct': [('torch.float32', [1, 1, 28, 28]), ('torch.float32', [16, 1, 5, 5]), - ('torch.float32', [16])], - 'output_struct': [('torch.float32', [1, 16, 28, 28])], - 'summary': [[3.029174327850342, -2.926689624786377, -0.06619918346405029], - [0.19919930398464203, -0.19974489510059357, 0.006269412115216255], - [0.19734230637550354, -0.18177609145641327, 0.007903944700956345], - [2.1166646480560303, -2.190781354904175, -0.003579073818400502]], 'stack_info': []} - -bench_dict = {'op_name': ['Functional_conv2d_0_forward_input.0', 'Functional_conv2d_0_forward_input.1', - 'Functional_conv2d_0_forward_input.2', 'Functional_conv2d_0_forward_output'], - 'input_struct': [('torch.float32', [1, 1, 28, 28]), ('torch.float32', [16, 1, 5, 5]), - ('torch.float32', [16])], - 'output_struct': [('torch.float32', [1, 16, 28, 28])], - 'summary': [[3.029174327850342, -2.926689624786377, -0.06619918346405029], - [0.19919930398464203, -0.19974489510059357, 0.006269412115216255], - [0.19734230637550354, -0.18177609145641327, 0.007903944700956345], - [2.1166646480560303, -2.190781354904175, -0.003579073818400502]], 'stack_info': []} - -tensor_list = [ - {'type': 'torch.Tensor', 'dtype': 'torch.float32', 'shape': [16, 1, 3, 3], 'Max': 0.33033010363578796, - 'Min': -0.331031858921051,'Mean': -0.030964046716690063, 'Norm': 2.2533628940582275, 'requires_grad': True, - 'full_op_name': 'Tensor.add_.0.forward_input.0'}, - {'type': 'torch.Tensor', 'dtype': 'torch.float32', 'shape': [16, 1, 3, 3], - 'Max': 0.003992878366261721, 'Min': -0.008102823048830032, 'Mean': -0.0002002553956117481, - 'Norm': 0.02844562754034996, 'requires_grad': False, 'full_op_name': 'Tensor.add_.0.forward_input.1'}, - {'full_op_name': 'Tensor.add_.0.forward_input.alpha.0', 'dtype': "", "shape": '[]', 'md5': None, - 'Max': -0.1, 'Min': -0.1, 'Mean': -0.1, 'Norm': -0.1, 'data_name': '-1'}, - {'type': 'torch.Tensor', 'dtype': 'torch.float32', 'shape': [16, 1, 3, 3], - 'Max': 0.33033010363578796, 'Min': -0.331031858921051, 'Mean': -0.030964046716690063, - 'Norm': 2.2533628940582275, 'requires_grad': True, 'full_op_name': 'Tensor.add_.0.forward_output.0'} -] - -result_op_dict = {'op_name': ['Tensor.add_.0.forward_input.0', 'Tensor.add_.0.forward_input.1', - 'Tensor.add_.0.forward_input.alpha.0', 'Tensor.add_.0.forward_output.0'], - 'input_struct': [('torch.float32', [16, 1, 3, 3]), ('torch.float32', [16, 1, 3, 3]), - ("", '[]')], - 'output_struct': [('torch.float32', [16, 1, 3, 3])], - 'summary': [[0.33033010363578796, -0.331031858921051, -0.030964046716690063, 2.2533628940582275], - [0.003992878366261721, -0.008102823048830032, -0.0002002553956117481, 0.02844562754034996], - [-0.1, -0.1, -0.1, -0.1], - [0.33033010363578796, -0.331031858921051, -0.030964046716690063, 2.2533628940582275]], - 'stack_info': []} - -o_result = [ - ['Functional_conv2d_0_forward_input.0', 'Functional_conv2d_0_forward_input.0', 'torch.float32', 'torch.float32', - [1, 1, 28, 28], [1, 1, 28, 28], 0.0, 0.0, 0.0, ' ', '0.0%', '0.0%', '0.0%', ' ', 3.029174327850342, -2.926689624786377, - -0.06619918346405029, 3.029174327850342, -2.926689624786377, -0.06619918346405029, '', '', 'None'], - ['Functional_conv2d_0_forward_input.1', 'Functional_conv2d_0_forward_input.1', 'torch.float32', 'torch.float32', - [16, 1, 5, 5], [16, 1, 5, 5], 0.0, 0.0, 0.0, ' ', '0.0%', '0.0%', '0.0%', ' ', 0.19919930398464203, -0.19974489510059357, - 0.006269412115216255, 0.19919930398464203, -0.19974489510059357, 0.006269412115216255, '', '', 'None'], - ['Functional_conv2d_0_forward_input.2', 'Functional_conv2d_0_forward_input.2', 'torch.float32', 'torch.float32', - [16], [16], 0.0, 0.0, 0.0, ' ', '0.0%', '0.0%', '0.0%', ' ', 0.19734230637550354, -0.18177609145641327, 0.007903944700956345, - 0.19734230637550354, -0.18177609145641327, 0.007903944700956345, '', '', 'None'], - ['Functional_conv2d_0_forward_output', 'Functional_conv2d_0_forward_output', 'torch.float32', 'torch.float32', - [1, 16, 28, 28], [1, 16, 28, 28], 0.0, 0.0, 0.0, ' ', '0.0%', '0.0%', '0.0%', ' ', 2.1166646480560303, -2.190781354904175, - -0.003579073818400502, 2.1166646480560303, -2.190781354904175, -0.003579073818400502, '', '', 'None']] - -npu_dict_aten = {'op_name': ['Aten__native_batch_norm_legit_functional.default_0_forward_input.0', - 'Aten__native_batch_norm_legit_functional.default_0_forward_input.1', - 'Aten__native_batch_norm_legit_functional.default_0_forward_input.2', - 'Aten__native_batch_norm_legit_functional.default_0_forward_input.3', - 'Aten__native_batch_norm_legit_functional.default_0_forward_input.4', - 'Aten__native_batch_norm_legit_functional.default_0_forward_output.0', - 'Aten__native_batch_norm_legit_functional.default_0_forward_output.1', - 'Aten__native_batch_norm_legit_functional.default_0_forward_output.2', - 'Aten__native_batch_norm_legit_functional.default_0_forward_output.3', - 'Aten__native_batch_norm_legit_functional.default_0_forward_output.4'], - 'input_struct': [('torch.float16', [256, 256, 14, 14]), ('torch.float32', [256]), - ('torch.float32', [256]), ('torch.float32', [256]), ('torch.float32', [256])], - 'output_struct': [('torch.float16', [256, 256, 14, 14]), ('torch.float32', [256]), - ('torch.float32', [256]), ('torch.float32', [256]), ('torch.float32', [256])], - 'summary': [[139.625, -127.5625, -0.0103607177734375], - [2.5276029109954834, -2.1788690090179443, -0.0008259844034910202], - [2.472219944000244, -2.845968723297119, -0.008756577968597412], - [2.763145923614502, -3.398397922515869, -0.052132632583379745], - [2.673110008239746, -3.149275064468384, 0.01613386906683445], - [13.5546875, -10.640625, -0.008758544921875], - [0.30550330877304077, -0.24485322833061218, -0.010361209511756897], - [623.9192504882812, 432.96826171875, 520.2276611328125], - [2.4797861576080322, -3.055997371673584, -0.04795549064874649], - [61.7945556640625, 42.59713363647461, 52.03831481933594]]} - -bench_dict_functional = { - 'op_name': ['Functional_batch_norm_0_forward_input.0', 'Functional_batch_norm_0_forward_input.1', - 'Functional_batch_norm_0_forward_input.2', 'Functional_batch_norm_0_forward_input.3', - 'Functional_batch_norm_0_forward_input.4', 'Functional_batch_norm_0_forward_output'], - 'input_struct': [('torch.float32', [256, 256, 14, 14]), ('torch.float32', [256]), ('torch.float32', [256]), - ('torch.float32', [256]), ('torch.float32', [256])], - 'output_struct': [('torch.float32', [256, 256, 14, 14])], - 'summary': [[3.061628818511963, -3.22507381439209, 3.634914173744619e-05], - [0.0005779837374575436, -0.0006301702815108001, 3.634906533989124e-06], - [0.9338104128837585, 0.9277191162109375, 0.930335283279419], - [1.0, 1.0, 1.0], [0.0, 0.0, 0.0], - [5.397906303405762, -5.796811580657959, 2.5283952709287405e-10]] -} - -aten_result = [ - ['Aten__native_batch_norm_legit_functional.default_0_forward_input.0', 'Functional_batch_norm_0_forward_input.0', - 'torch.float16', 'torch.float32', [256, 256, 14, 14], [256, 256, 14, 14], 136.56337118148804, -124.33742618560791, - -0.010397066915174946, ' ', '4460.480981749501%', '3855.335826136584%', '28603.33536971545%', ' ', 139.625, - -127.5625, -0.0103607177734375, 3.061628818511963, -3.22507381439209, 3.634914173744619e-05, 'Warning', - 'Need double check api accuracy.', 'None'], - ['Aten__native_batch_norm_legit_functional.default_0_forward_input.1', 'Functional_batch_norm_0_forward_input.1', - 'torch.float32', 'torch.float32', [256], [256], 2.527024927258026, -2.1782388387364335, -0.0008296193100250093, - ' ', '437213.84590749856%', '345658.76916858414%', '22823.676544842117%', ' ', 2.5276029109954834, - -2.1788690090179443, -0.0008259844034910202, 0.0005779837374575436, -0.0006301702815108001, 3.634906533989124e-06, - 'Warning', 'Need double check api accuracy.', 'None'], - ['Aten__native_batch_norm_legit_functional.default_0_forward_input.2', 'Functional_batch_norm_0_forward_input.2', - 'torch.float32', 'torch.float32', [256], [256], 1.5384095311164856, -3.7736878395080566, -0.9390918612480164, ' ', - '164.74538192025793%', '406.7705163736246%', '100.94122819224167%', ' ', 2.472219944000244, -2.845968723297119, - -0.008756577968597412, 0.9338104128837585, 0.9277191162109375, 0.930335283279419, 'Warning', - 'Need double check api accuracy.', 'None'], - ['Aten__native_batch_norm_legit_functional.default_0_forward_input.3', 'Functional_batch_norm_0_forward_input.3', - 'torch.float32', 'torch.float32', [256], [256], 1.763145923614502, -4.398397922515869, -1.0521326325833797, ' ', - '176.3145923614502%', '439.8397922515869%', '105.21326325833797%', ' ', 2.763145923614502, -3.398397922515869, - -0.052132632583379745, 1.0, 1.0, 1.0, 'Warning', 'Need double check api accuracy.', 'None'], - ['Aten__native_batch_norm_legit_functional.default_0_forward_input.4', 'Functional_batch_norm_0_forward_input.4', - 'torch.float32', 'torch.float32', [256], [256], 2.673110008239746, -3.149275064468384, 0.01613386906683445, ' ', - 'N/A', 'N/A', 'N/A', ' ', 2.673110008239746, -3.149275064468384, 0.01613386906683445, 0.0, 0.0, 0.0, 'Warning', - 'Need double check api accuracy.', 'None'], - ['Aten__native_batch_norm_legit_functional.default_0_forward_output.0', 'Functional_batch_norm_0_forward_output', - 'torch.float16', 'torch.float32', [256, 256, 14, 14], [256, 256, 14, 14], 8.156781196594238, -4.843813419342041, - -0.008758545174714527, ' ', '151.11009228611078%', '83.55995967687207%', '3464072756.115108%', ' ', 13.5546875, - -10.640625, -0.008758544921875, 5.397906303405762, -5.796811580657959, 2.5283952709287405e-10, 'Warning', - 'Need double check api accuracy.', 'None'], - ['Aten__native_batch_norm_legit_functional.default_0_forward_output.1', 'Nan', 'torch.float32', 'Nan', [256], 'Nan', - ' ', ' ', ' ', ' ', ' ', 0.30550330877304077, -0.24485322833061218, -0.010361209511756897, 'Nan', 'Nan', 'Nan', - 'Yes', '', 'None'], - ['Aten__native_batch_norm_legit_functional.default_0_forward_output.2', 'Nan', 'torch.float32', 'Nan', [256], 'Nan', - ' ', ' ', ' ', ' ', ' ', 623.9192504882812, 432.96826171875, 520.2276611328125, 'Nan', 'Nan', 'Nan', - 'Yes', '', 'None'], - ['Aten__native_batch_norm_legit_functional.default_0_forward_output.3', 'Nan', 'torch.float32', 'Nan', [256], 'Nan', - ' ', ' ', ' ', ' ', ' ', 2.4797861576080322, -3.055997371673584, -0.04795549064874649, 'Nan', 'Nan', 'Nan', - 'Yes', '', 'None'], - ['Aten__native_batch_norm_legit_functional.default_0_forward_output.4', 'Nan', 'torch.float32', 'Nan', [256], 'Nan', - ' ', ' ', ' ', ' ', ' ', 61.7945556640625, 42.59713363647461, 52.03831481933594, 'Nan', 'Nan', 'Nan', - 'Yes', '', 'None']] - -highlight_dict = {'red_rows': [], 'yellow_rows': []} - -num_0, num_1, num_2, num_3 = 0, 1, 2, 3 -summary_line_input = ['Functional_batch_norm_0_forward_input.0', 'Functional_batch_norm_0_forward_input.0', - 'torch.float16', - 'torch.float32', [256, 256, 14, 14], [256, 256, 14, 14], 0.01, 0, 0, 0, 1, 1, 1, 1, 1.01, 1, 1, 1, - 'Yes', ''] -summary_line_1 = ['Functional_batch_norm_0_forward_output.0', 'Functional_batch_norm_0_forward_output.0', - 'torch.float16', - 'torch.float32', [256, 256, 14, 14], [256, 256, 14, 14], 10, 0, 0, 0, 2, 0, 1, 1, 1, 1, 1, 1, - 'Warning', ''] -summary_line_2 = ['Functional_batch_norm_0_forward_output.1', 'Functional_batch_norm_0_forward_output.1', - 'torch.float16', - 'torch.float32', [256, 256, 14, 14], [256, 256, 14, 14], 0.02, 0, 0, 0, 0.12, 0, 1, 1, 0.1, 1, 1, 1, - 'Warning', ''] -summary_line_3 = ['Functional_batch_norm_0_forward_output.2', 'Functional_batch_norm_0_forward_output.2', - 'torch.float16', - 'torch.float32', [256, 256, 14, 14], [256, 256, 14, 14], 0, 0, 0, 0, 2, 0, 1, 1, 1, 1, 1, 1, - 'Warning', ''] -line_input = ['Functional_batch_norm_0_forward_input.0', 'Functional_batch_norm_0_forward_input.0', 'torch.float16', - 'torch.float32', [256, 256, 14, 14], [256, 256, 14, 14], 1, 1, 1, 0.95, 1, 1, 1, 1, 1, 1.01, 1, 1, 1, - 'Yes', ''] -line_1 = ['Functional_batch_norm_0_forward_output.0', 'Functional_batch_norm_0_forward_output.0', 'torch.float16', - 'torch.float32', [256, 256, 14, 14], [256, 256, 14, 14], 0.8, 1, 1, 0.59, 1, 'nan', 0, 1, 1, 19, 1, 1, 1, - 'Warning', ''] -line_2 = ['Functional_batch_norm_0_forward_output.1', 'Functional_batch_norm_0_forward_output.1', 'torch.float16', - 'torch.float32', [256, 256, 14, 14], [256, 256, 14, 14], 0.9, 1, 1, 0.8, 1, 0, 0.12, 0, 1, 1, 0.1, 1, 1, 1, - 'Warning', ''] -line_3 = ['Functional_batch_norm_0_forward_output.2', 'Functional_batch_norm_0_forward_output.2', 'torch.float16', - 'torch.float32', [256, 256, 14, 14], [256, 256, 14, 14], 0.8, 1.1e+10, 1, 0.85, 1, 9, 0.12, 0, 1, 1, 0.1, 1, - 1, 1, 'Warning', ''] - -op_data = { - 'input_args': [{'type': 'torch.Tensor', 'dtype': 'torch.float32', 'shape': [16, 1, 3, 3], - 'Max': 0.33033010363578796, 'Min': -0.331031858921051,'Mean': -0.030964046716690063, - 'Norm': 2.2533628940582275, 'requires_grad': True}, - {'type': 'torch.Tensor', 'dtype': 'torch.float32', 'shape': [16, 1, 3, 3], - 'Max': 0.003992878366261721, 'Min': -0.008102823048830032, 'Mean': -0.0002002553956117481, - 'Norm': 0.02844562754034996, 'requires_grad': False}], - 'input_kwargs': {'alpha': {'type': 'float', 'value': -0.1}}, - 'output': [{'type': 'torch.Tensor', 'dtype': 'torch.float32', 'shape': [16, 1, 3, 3], - 'Max': 0.33033010363578796, 'Min': -0.331031858921051,'Mean': -0.030964046716690063, - 'Norm': 2.2533628940582275, 'requires_grad': True}]} - -op_name = "Tensor.add_0.0.forward" - -op_result = [ - {'type': 'torch.Tensor', 'dtype': 'torch.float32', 'shape': [16, 1, 3, 3], - 'Max': 0.33033010363578796, 'Min': -0.331031858921051, 'Mean': -0.030964046716690063, - 'Norm': 2.2533628940582275, 'requires_grad': True, 'full_op_name': 'Tensor.add_0.0.forward_input.0'}, - {'type': 'torch.Tensor', 'dtype': 'torch.float32', 'shape': [16, 1, 3, 3], - 'Max': 0.003992878366261721, 'Min': -0.008102823048830032, 'Mean': -0.0002002553956117481, - 'Norm': 0.02844562754034996, 'requires_grad': False, 'full_op_name': 'Tensor.add_0.0.forward_input.1'}, - {'full_op_name': 'Tensor.add_0.0.forward_input.alpha.0', 'dtype': "", 'shape': '[]', 'md5': None, - 'Max': -0.1, 'Min': -0.1, 'Mean': -0.1, 'Norm': -0.1, 'data_name': '-1'}, - {'type': 'torch.Tensor', 'dtype': 'torch.float32', 'shape': [16, 1, 3, 3], - 'Max': 0.33033010363578796, 'Min': -0.331031858921051, 'Mean': -0.030964046716690063, - 'Norm': 2.2533628940582275, 'requires_grad': True, 'full_op_name': 'Tensor.add_0.0.forward_output.0'}] - - -class TestUtilsMethods(unittest.TestCase): - - def test_check_graph_mode(self): - op1 = "Aten" - op2 = "torch" - self.assertTrue(compare.check_graph_mode(op1, op2)) - self.assertTrue(compare.check_graph_mode(op2, op1)) - self.assertFalse(compare.check_graph_mode(op1, op1)) - self.assertFalse(compare.check_graph_mode(op2, op2)) - - def test_check_op(self): - fuzzy_match = False - result = compare.check_op(npu_dict, bench_dict, fuzzy_match) - self.assertEqual(result, True) - - def test_merge_tensor(self): - op_dict = compare.merge_tensor(tensor_list, True, False) - self.assertEqual(op_dict, result_op_dict) - - def test_read_op(self): - result = compare.read_op(op_data, op_name) - self.assertEqual(result, op_result) - - def test_match_op(self): - fuzzy_match = False - a, b = compare.match_op([npu_dict], [bench_dict], fuzzy_match) - self.assertEqual(a, 0) - self.assertEqual(b, 0) - - def test_get_accuracy(self): - result = [] - compare.get_accuracy(result, npu_dict, bench_dict, highlight_dict) - self.assertEqual(result, o_result) - - def test_get_accuracy_graph_mode(self): - result = [] - compare.get_accuracy(result, npu_dict_aten, bench_dict_functional, highlight_dict) - self.assertEqual(result, aten_result) - - def test_find_error_rows(self): - summary_result = [summary_line_input, summary_line_1, summary_line_2, summary_line_3] - highlight_dict = {'red_rows': [], 'yellow_rows': []} - compare.find_error_rows(summary_result, 0, 1, highlight_dict, summary_compare=True) - self.assertEqual(highlight_dict, {'red_rows': [], 'yellow_rows': []}) - - def test_find_compare_result_error_rows(self): - result = [line_input, line_1, line_2, line_3] - result_df = pd.DataFrame(result) - highlight_dict = {'red_rows': [], 'yellow_rows': []} - compare.find_compare_result_error_rows(result_df, highlight_dict, False, False) - self.assertEqual(highlight_dict, {'red_rows': [num_1, num_3], 'yellow_rows': [num_2]}) - - def test_rename_api(self): - test_name_1 = "Distributed.broadcast.0.forward.input.0" - expect_name_1 = "Distributed.broadcast.input.0" - actual_name_1 = compare.rename_api(test_name_1, "forward") - self.assertEqual(actual_name_1, expect_name_1) - - test_name_2 = "Torch.sum.0.backward.output.0" - expect_name_2 = "Torch.sum.output.0" - actual_name_2 = compare.rename_api(test_name_2, "backward") - self.assertEqual(actual_name_2, expect_name_2) diff --git a/debug/accuracy_tools/msprobe/test/pytorch_ut/config_checking/test_config_checking.py b/debug/accuracy_tools/msprobe/test/pytorch_ut/config_checking/test_config_checking.py deleted file mode 100644 index 8275bcb718..0000000000 --- a/debug/accuracy_tools/msprobe/test/pytorch_ut/config_checking/test_config_checking.py +++ /dev/null @@ -1,107 +0,0 @@ -import os -import random -import unittest -import torch -import json -import numpy as np -import torch.nn as nn -from multiprocessing import Process -from time import sleep -from msprobe.pytroch.config_checking.config_checker import ConfigChecker - -testdir = os.path.dirname(__file__) -config_checking_dir = os.path.dirname(testdir) -temp_dir = os.path.join(config_checking_dir, "temp") -os.makedirs(temp_dir, exist_ok=True) - - -def seed_all(seed=1234, mode=False): - random.seed(seed) - os.environ['PYTHONHASHSEED'] = str(seed) - np.random.seed(seed) - torch.manual_seed(seed) - torch.use_deterministic_algorithms(mode) - - -class MockModule(nn.Module): - def __init__(self): - super().__init__() - self.linear = nn.Linear(10, 5) - self.relu = nn.ReLU() - - def forward(self, x): - x1 = self.linear(x) - x2 = self.relu(x1) - return x2 - - -def get_test_dataset(): - inputs = [torch.rand(10, 10) for _ in range(10)] - labels = [torch.randint(0, 5, (10,)) for _ in range(10)] - return zip(inputs, labels) - - -def get_test_model(): - test_module = MockModule() - nn.init.constant_(test_module.linear.weight, 1.0) - nn.init.constant_(test_module.linear.bias, 1.0) - return test_module - - -@unittest.mock.patch("msprobe.pytroch.config_checking.checkers.pip_checker.collect_pip_data") -@unittest.mock.patch("msprobe.pytroch.config_checking.checkers.env_args_checker.collect_env_data") -def train_test(config_dict, seed, mock_env, mock_pip): - mock_env.return_value = {"HCCL_DETERMINISTIC": False} - if seed == 1234: - mock_pip.return_value = "transformers=0.0.1" - else: - mock_pip.return_value = "transformers=0.0.2" - seed_all(seed) - - loss_fun = nn.CrossEntropyLoss() - test_module = get_test_model() - optimizer = torch.optim.SGD(test_module.parameters(), lr=1e-2) - - config_path = os.path.join(temp_dir, "config.json") - json.dump(config_dict, open(config_path, 'w', encoding='utf-8')) - ConfigChecker(config_path, test_module) - os.remove(config_path) - - for input_data, label in get_test_dataset(): - output = test_module(input_data) - loss = loss_fun(output, label) - optimizer.zero_grad() - loss.backward() - optimizer.step() - - -def process_train_test(config_dict, seed=1234): - p = Process(target=train_test, args=(config_dict, seed)) - p.start() - sleep(3) - - -class TestConfigChecker(unittest.TestCase): - def test_all(self): - config_dict1 = { - "env args": True, - "pip data": True, - "output zip path": os.path.join(temp_dir, "config_check_pack1.zip") - } - process_train_test(config_dict1, 1234) - - config_dict2 = { - "env args": True, - "pip data": True, - "output zip path": os.path.join(temp_dir, "config_check_pack2.zip") - } - process_train_test(config_dict2, 1233) - - ConfigChecker.compare(config_dict1["output zip path"], - config_dict2["output zip path"], - os.path.join(temp_dir, "compare_output")) - - compare_output_dir = os.path.join(temp_dir, "compare_output", "output") - with open(os.path.join(compare_output_dir, "pip_data_check_result.txt"), 'r', encoding='utf-8') as file: - lines = file.readlines() - self.assertEqual(lines[1], " package_name:transformers, npu_version:0.0.1, bench_version:0.0.2\n") \ No newline at end of file diff --git a/debug/accuracy_tools/msprobe/test/pytorch_ut/functional/test_dump_module.py b/debug/accuracy_tools/msprobe/test/pytorch_ut/functional/test_dump_module.py deleted file mode 100644 index d67adf2f91..0000000000 --- a/debug/accuracy_tools/msprobe/test/pytorch_ut/functional/test_dump_module.py +++ /dev/null @@ -1,15 +0,0 @@ -import unittest - -import torch.nn as nn -from msprobe.pytorch import PrecisionDebugger -from msprobe.pytorch.functional.dump_module import module_dump, module_count - - -class TestDumpModule(unittest.TestCase): - def setUp(self): - self.module = nn.Linear(in_features=8, out_features=4) - - def test_module_dump(self): - PrecisionDebugger(dump_path="./dump") - module_dump(self.module, "TestModule") - self.assertTrue("TestModule" in module_count) diff --git a/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/builder/test_graph_builder.py b/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/builder/test_graph_builder.py deleted file mode 100644 index 9433bc1363..0000000000 --- a/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/builder/test_graph_builder.py +++ /dev/null @@ -1,99 +0,0 @@ -import unittest -from unittest.mock import MagicMock, patch -from msprobe.pytorch.visualization.builder.graph_builder import GraphBuilder, Graph, BaseNode, NodeOp - - -class TestGraphBuilder(unittest.TestCase): - - def setUp(self): - self.construct_path = "step/rank/construct.json" - self.data_path = "step/rank/dump.json" - self.model_name = "TestModel" - self.graph = Graph(self.model_name) - self.construct_dict = { - "Tensor1": "Module1", - "Module1": None - } - self.data_dict = { - "Module1": {"data": "data for Module1"}, - "Tensor1": {"data": "data for Tensor1"} - } - - @patch('msprobe.pytorch.visualization.builder.graph_builder.load_json_file') - @patch('msprobe.pytorch.visualization.builder.graph_builder.load_data_json_file') - def test_build(self, mock_load_data_json_file, mock_load_json_file): - mock_load_data_json_file.return_value = self.data_dict - mock_load_json_file.return_value = self.construct_dict - - graph = GraphBuilder.build(self.construct_path, self.data_path, self.model_name) - self.assertIsNotNone(graph) - self.assertIsInstance(graph, Graph) - self.assertEqual(len(graph.node_map), 3) - - @patch('msprobe.pytorch.visualization.builder.graph_builder.save_json_file') - def test_to_json(self, mock_save_json_file): - GraphBuilder.to_json("step/rank/output.vis", self.graph) - mock_save_json_file.assert_called_once() - - @patch('msprobe.pytorch.visualization.graph.node_op.NodeOp.get_node_op') - @patch('msprobe.pytorch.visualization.builder.msprobe_adapter.get_input_output', return_value=([], [])) - def test__init_nodes(self, mock_get_input_output, mock_get_node_op): - GraphBuilder._init_nodes(self.graph, self.construct_dict, self.data_dict) - mock_get_node_op.assert_any_call("Tensor1") - mock_get_node_op.assert_any_call("Module1") - self.assertIs(self.graph.root, self.graph.get_node("TestModel")) - - def test__create_or_get_node(self): - node_op = MagicMock() - data_dict = {"node1": {}} - node = GraphBuilder._create_or_get_node(self.graph, data_dict, node_op, "node1") - self.assertIn("node1", self.graph.node_map) - self.assertEqual(node.input_data, {}) - self.assertEqual(node.output_data, {}) - - def test__handle_backward_upnode_missing(self): - construct_dict = {'Module.module.a.forward.0': 'Module.root.forward.0', 'Module.module.a.backward.0': None, - 'Module.root.forward.0': None, 'Module.root.backward.0': None, - 'Module.module.b.forward.0': 'Module.root.forward.0', - 'Module.module.b.backward.0': 'Module.root.backward.0', 'Module.module.c.backward.0': None} - node_id_a = GraphBuilder._handle_backward_upnode_missing(construct_dict, 'Module.module.a.backward.0', None) - self.assertEqual(node_id_a, 'Module.root.backward.0') - node_id_b = GraphBuilder._handle_backward_upnode_missing(construct_dict, 'Module.module.b.backward.0', - 'Module.root.backward.0') - self.assertEqual(node_id_b, 'Module.root.backward.0') - node_id_c = GraphBuilder._handle_backward_upnode_missing(construct_dict, 'Module.module.c.backward.0', None) - self.assertIsNone(node_id_c) - - def test__collect_apis_between_modules_only_apis(self): - graph = Graph('TestNet') - graph.root.subnodes = [BaseNode(NodeOp.function_api, 'Tensor.a.0'), BaseNode(NodeOp.function_api, 'Tensor.b.0')] - GraphBuilder._collect_apis_between_modules(graph) - self.assertEqual(len(graph.root.subnodes), 1) - self.assertEqual(graph.root.subnodes[0].op, NodeOp.api_collection) - self.assertEqual(len(graph.root.subnodes[0].subnodes), 2) - self.assertEqual(graph.root.subnodes[0].id, 'Apis_Between_Modules.0') - - def test__collect_apis_between_modules_mixed_nodes(self): - graph = Graph('TestNet') - graph.root.subnodes = [BaseNode(NodeOp.function_api, 'Tensor.a.0'), BaseNode(NodeOp.module, 'Module.a.0'), - BaseNode(NodeOp.module, 'Module.b.0'), BaseNode(NodeOp.function_api, 'Tensor.b.0'), - BaseNode(NodeOp.function_api, 'Tensor.c.0'), BaseNode(NodeOp.module, 'Module.a.1')] - GraphBuilder._collect_apis_between_modules(graph) - self.assertEqual(len(graph.root.subnodes), 5) - self.assertEqual(graph.root.subnodes[0].op, NodeOp.function_api) - self.assertEqual(graph.root.subnodes[1].op, NodeOp.module) - self.assertEqual(graph.root.subnodes[3].op, NodeOp.api_collection) - self.assertEqual(len(graph.root.subnodes[3].subnodes), 2) - self.assertEqual(graph.root.subnodes[3].id, 'Apis_Between_Modules.0') - - def test__collect_apis_between_modules_only_modules(self): - graph = Graph('TestNet') - graph.root.subnodes = [BaseNode(NodeOp.module, 'Module.a.0'), BaseNode(NodeOp.module, 'Module.b.0'), - BaseNode(NodeOp.module, 'Module.a.1')] - GraphBuilder._collect_apis_between_modules(graph) - self.assertEqual(len(graph.root.subnodes), 3) - self.assertEqual(graph.root.subnodes[0].op, NodeOp.module) - self.assertEqual(graph.root.subnodes[1].op, NodeOp.module) - self.assertEqual(graph.root.subnodes[2].op, NodeOp.module) - self.assertEqual(len(graph.root.subnodes[0].subnodes), 0) - self.assertEqual(graph.root.subnodes[0].id, 'Module.a.0') diff --git a/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/builder/test_msprobe_adapter.py b/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/builder/test_msprobe_adapter.py deleted file mode 100644 index f023128b8c..0000000000 --- a/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/builder/test_msprobe_adapter.py +++ /dev/null @@ -1,104 +0,0 @@ -import unittest -from unittest.mock import patch -from msprobe.pytorch.visualization.builder.msprobe_adapter import ( - get_compare_mode, - run_real_data, - get_input_output, - compare_data, - format_node_data, - compare_node, - _format_decimal_string, - _format_data, - compare_mapping_data -) -from msprobe.pytorch.visualization.utils import GraphConst - - -class TestMsprobeAdapter(unittest.TestCase): - @patch('msprobe.pytorch.visualization.builder.msprobe_adapter.task_dumppath_get', return_value=(True, False)) - def test_get_compare_mode_summary(self, mock_task_dumppath_get): - mode = get_compare_mode("dummy_param") - self.assertEqual(mode, GraphConst.SUMMARY_COMPARE) - - @patch('msprobe.pytorch.visualization.builder.msprobe_adapter._do_multi_process') - def test_run_real_data(self, mock_do_multi_process): - run_real_data("dump_path", "csv_path") - mock_do_multi_process.assert_called_once_with("dump_path", "csv_path") - - def test_get_input_output(self): - node_data = { - 'input_args': [{'type': 'torch.Tensor', 'dtype': 'torch.int64', 'shape': [5], - 'Max': 2049.0, 'Min': 0.0, 'Mean': 410.20001220703125, 'Norm': 2049.0009765625, - 'requires_grad': False, 'full_op_name': 'Distributed.broadcast.0.forward_input.0'}, - {'type': 'int', 'value': 0}], - 'input_kwargs': {'group': None}, - 'output': [{'type': 'torch.Tensor', 'dtype': 'torch.int64', 'shape': [5], - 'Max': 2049.0, 'Min': 0.0, 'Mean': 410.20001220703125, 'Norm': 2049.0009765625, - 'requires_grad': False, 'full_op_name': 'Distributed.broadcast.0.forward_output.0'}, - {'type': 'int', 'value': 0}, None] - } - node_id = "Distributed.broadcast.0.forward" - input_data, output_data = get_input_output(node_data, node_id) - self.assertIn("Distributed.broadcast.0.forward_output.0", output_data) - self.assertIn("Distributed.broadcast.0.forward_input.0", input_data) - - def test_compare_data(self): - data_dict_list1 = {'key1': {'type': 'Type1', 'dtype': 'DType1', 'shape': 'Shape1'}} - data_dict_list2 = {'key1': {'type': 'Type1', 'dtype': 'DType1', 'shape': 'Shape1'}} - data_dict_list3 = {'key1': {'type': 'Type2', 'dtype': 'DType1', 'shape': 'Shape1'}} - data_dict_list4 = {} - self.assertTrue(compare_data(data_dict_list1, data_dict_list2)) - self.assertFalse(compare_data(data_dict_list1, data_dict_list3)) - self.assertFalse(compare_data(data_dict_list1, data_dict_list4)) - - def test_format_node_data(self): - data_dict = {'node1': {'data_name': 'data1', 'full_op_name': 'op1'}} - result = format_node_data(data_dict) - self.assertNotIn('data_name', result['node1']) - self.assertNotIn('requires_grad', result['node1']) - - @patch('msprobe.pytorch.visualization.builder.msprobe_adapter.get_accuracy') - def test_compare_node(self, mock_get_accuracy): - node_ids = ["node1", "node2"] - data_dicts = [{'node1': {"input_args": [], "input_kwargs": {}, "output": {}}}, - {'node2': {"input_args": [], "input_kwargs": {}, "output": {}}}] - stack_json_data = {} - result = compare_node(node_ids, data_dicts, stack_json_data, False, False) - mock_get_accuracy.assert_called_once() - self.assertIsInstance(result, list) - - def test__format_decimal_string(self): - s = "0.123456789%" - formatted_s = _format_decimal_string(s) - self.assertIn("0.123457%", formatted_s) - self.assertEqual('0.123457', _format_decimal_string('0.12345678')) - self.assertEqual('-1', _format_decimal_string('-1')) - self.assertEqual('0.0.25698548%', _format_decimal_string('0.0.25698548%')) - - def test__format_data(self): - data_dict = {'value': 0.123456789, 'value1': None, 'value2': "", 'value3': 1.123123123123e-11, - 'value4': torch.inf, 'value5': -1} - _format_data(data_dict) - self.assertEqual(data_dict['value'], '0.123457') - self.assertEqual(data_dict['value1'], 'null') - self.assertEqual(data_dict['value2'], '') - self.assertEqual(data_dict['value3'], '1.123123e-11') - self.assertEqual(data_dict['value4'], 'inf') - self.assertEqual(data_dict['value5'], '-1') - - all_none_dict = {'a': None, 'b': None, 'c': None, 'd': None, 'e': None} - _format_data(all_none_dict) - self.assertEqual({'value': 'null'}, all_none_dict) - - def test_compare_mapping_data(self): - dict1 = {'a': {'shape': [1, 2, 3]}, 'b': {'shape': [1, 2, 3]}, 'c': {'shape': [1, 2, 3]}} - dict2 = {'a': {'shape': [1, 2, 3]}, 'b': {'shape': [1, 2, 3]}, 'c': {'shape': [1, 2, 3]}} - dict3 = {'a': {'shape': [1, 2, 3]}, 'b': {'shape': [1, 2, 3]}} - dict4 = {'a': {'shape': [2, 1, 3]}, 'b': {'shape': [1, 2, 3]}} - dict5 = {'a': {'shape': [2, 2, 3]}, 'b': {'shape': [1, 2, 3]}} - dict6 = {'a': {'type': 'str'}} - self.assertTrue(compare_mapping_data(dict1, dict2)) - self.assertTrue(compare_mapping_data(dict1, dict3)) - self.assertTrue(compare_mapping_data(dict1, dict4)) - self.assertFalse(compare_mapping_data(dict1, dict5)) - self.assertTrue(compare_mapping_data(dict1, dict6)) diff --git a/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/compare/test_graph_comparator.py b/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/compare/test_graph_comparator.py deleted file mode 100644 index cb69ac7723..0000000000 --- a/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/compare/test_graph_comparator.py +++ /dev/null @@ -1,143 +0,0 @@ -import unittest -from unittest.mock import patch -from unittest.mock import MagicMock -from msprobe.pytorch.visualization.compare.graph_comparator import GraphComparator -from msprobe.pytorch.visualization.graph.graph import Graph, BaseNode, NodeOp -from msprobe.pytorch.visualization.utils import GraphConst - - -class TestGraphComparator(unittest.TestCase): - - def setUp(self): - self.graphs = [Graph("model1"), Graph("model2")] - self.data_paths = ["step1/rank/dump.json", "step2/rank/dump.json"] - self.stack_path = "step1/rank/stack.json" - self.output_path = "output/output.vis" - - @patch('msprobe.pytorch.visualization.compare.graph_comparator.get_compare_mode') - @patch('msprobe.pytorch.visualization.compare.graph_comparator.load_json_file') - @patch('msprobe.pytorch.visualization.compare.graph_comparator.load_data_json_file') - def test__parse_param(self, mock_load_data_json_file, mock_load_json_file, mock_get_compare_mode): - mock_load_data_json_file.return_value = "data_dict" - mock_load_json_file.return_value = "construct_dict" - mock_get_compare_mode.return_value = GraphConst.SUMMARY_COMPARE - self.comparator = GraphComparator(self.graphs, self.data_paths, self.stack_path, self.output_path) - self.comparator._parse_param(self.data_paths, self.stack_path, self.output_path) - - self.assertEqual(self.comparator.dump_path_param, { - 'npu_json_path': self.data_paths[0], - 'bench_json_path': self.data_paths[1], - 'stack_json_path': self.stack_path, - 'is_print_compare_log': True - }) - self.assertEqual(self.comparator.output_path, self.output_path) - - @patch('msprobe.pytorch.visualization.compare.graph_comparator.get_compare_mode') - @patch('msprobe.pytorch.visualization.compare.graph_comparator.load_json_file') - @patch('msprobe.pytorch.visualization.compare.graph_comparator.load_data_json_file') - def test_compare(self, mock_load_data_json_file, mock_load_json_file, mock_get_compare_mode): - mock_load_data_json_file.return_value = "data_dict" - mock_load_json_file.return_value = "construct_dict" - mock_get_compare_mode.return_value = GraphConst.SUMMARY_COMPARE - comparator = GraphComparator(self.graphs, self.data_paths, self.stack_path, self.output_path) - comparator._compare_nodes = MagicMock() - comparator._postcompare = MagicMock() - - comparator.compare() - - comparator._compare_nodes.assert_called_once() - comparator._postcompare.assert_called_once() - - @patch('msprobe.pytorch.visualization.compare.graph_comparator.get_compare_mode') - @patch('msprobe.pytorch.visualization.compare.graph_comparator.load_json_file') - @patch('msprobe.pytorch.visualization.compare.graph_comparator.load_data_json_file') - def test_add_compare_result_to_node(self, mock_load_data_json_file, mock_load_json_file, mock_get_compare_mode): - mock_load_data_json_file.return_value = "data_dict" - mock_load_json_file.return_value = "construct_dict" - mock_get_compare_mode.return_value = GraphConst.SUMMARY_COMPARE - node = MagicMock() - compare_result_list = [("output1", "data1"), ("input1", "data2")] - - comparator = GraphComparator(self.graphs, self.data_paths, self.stack_path, self.output_path) - comparator.ma = MagicMock() - comparator.ma.prepare_real_data.return_value = True - - comparator.add_compare_result_to_node(node, compare_result_list) - comparator.ma.prepare_real_data.assert_called_once_with(node) - node.data.update.assert_not_called() - - @patch('msprobe.pytorch.visualization.graph.node_colors.NodeColors.get_node_error_status') - @patch('msprobe.pytorch.visualization.utils.get_csv_df') - @patch('msprobe.pytorch.visualization.builder.msprobe_adapter.run_real_data') - @patch('msprobe.pytorch.visualization.compare.graph_comparator.get_compare_mode') - @patch('msprobe.pytorch.visualization.compare.graph_comparator.load_json_file') - @patch('msprobe.pytorch.visualization.compare.graph_comparator.load_data_json_file') - def test__postcompare(self, mock_load_data_json_file, mock_load_json_file, mock_get_compare_mode, - mock_run_real_data, mock_get_csv_df, mock_get_node_error_status): - mock_load_data_json_file.return_value = "data_dict" - mock_load_json_file.return_value = "construct_dict" - mock_get_compare_mode.return_value = GraphConst.SUMMARY_COMPARE - mock_df = MagicMock() - mock_df.iterrows = MagicMock(return_value=[(None, MagicMock())]) - mock_run_real_data.return_value = mock_df - mock_get_csv_df.return_value = mock_df - mock_get_node_error_status.return_value = True - comparator = GraphComparator(self.graphs, self.data_paths, self.stack_path, self.output_path) - comparator.ma = MagicMock() - comparator.ma.is_real_data_compare.return_value = True - comparator._handle_api_collection_index = MagicMock() - comparator.ma.compare_nodes = [MagicMock()] - comparator.ma.parse_result = MagicMock(return_value=(0.9, None)) - - comparator._postcompare() - - comparator._handle_api_collection_index.assert_called_once() - comparator.ma.add_error_key.assert_called() - - @patch('msprobe.pytorch.visualization.compare.graph_comparator.get_compare_mode') - @patch('msprobe.pytorch.visualization.compare.graph_comparator.load_json_file') - @patch('msprobe.pytorch.visualization.compare.graph_comparator.load_data_json_file') - def test__handle_api_collection_index(self, mock_load_data_json_file, mock_load_json_file, mock_get_compare_mode): - mock_load_data_json_file.return_value = "data_dict" - mock_load_json_file.return_value = "construct_dict" - mock_get_compare_mode.return_value = GraphConst.SUMMARY_COMPARE - comparator = GraphComparator(self.graphs, self.data_paths, self.stack_path, self.output_path) - apis = BaseNode(NodeOp.api_collection, 'Apis_Between_Modules.0') - api1 = BaseNode(NodeOp.function_api, 'Tensor.a.0') - api1.data = {GraphConst.JSON_INDEX_KEY: 0.9} - api2 = BaseNode(NodeOp.function_api, 'Tensor.b.0') - api2.data = {GraphConst.JSON_INDEX_KEY: 0.6} - apis.subnodes = [api1, api2] - sub_nodes = [BaseNode(NodeOp.module, 'Module.a.0'), apis, BaseNode(NodeOp.module, 'Module.a.1')] - comparator.graph_n.root.subnodes = sub_nodes - comparator._handle_api_collection_index() - self.assertEqual(comparator.graph_n.root.subnodes[1].data.get(GraphConst.JSON_INDEX_KEY), 0.6) - - @patch('msprobe.pytorch.visualization.builder.msprobe_adapter.compare_node') - @patch('msprobe.pytorch.visualization.graph.graph.Graph.match') - @patch('msprobe.pytorch.visualization.graph.graph.Graph.mapping_match') - @patch('msprobe.pytorch.visualization.compare.graph_comparator.get_compare_mode') - @patch('msprobe.pytorch.visualization.compare.graph_comparator.load_json_file') - @patch('msprobe.pytorch.visualization.compare.graph_comparator.load_data_json_file') - def test__compare_nodes(self, mock_load_data_json_file, mock_load_json_file, mock_get_compare_mode, - mock_mapping_match, mock_match, mock_compare_node): - node_n = BaseNode(NodeOp.function_api, 'Tensor.a.0') - node_b = BaseNode(NodeOp.function_api, 'Tensor.b.0') - mock_load_data_json_file.return_value = {} - mock_load_json_file.return_value = {} - mock_get_compare_mode.return_value = GraphConst.SUMMARY_COMPARE - mock_mapping_match.return_value = (node_b, [], []) - mock_compare_node.return_value = ['result'] - comparator = GraphComparator(self.graphs, self.data_paths, self.stack_path, self.output_path) - comparator.mapping_config = True - comparator._compare_nodes(node_n) - self.assertEqual(node_n.matched_node_link, ['Tensor.b.0']) - self.assertEqual(node_b.matched_node_link, ['Tensor.a.0']) - comparator.mapping_config = False - node_n = BaseNode(NodeOp.function_api, 'Tensor.a.0') - node_b = BaseNode(NodeOp.function_api, 'Tensor.a.0') - mock_match.return_value = (node_b, []) - comparator._compare_nodes(node_n) - self.assertEqual(node_n.matched_node_link, ['Tensor.a.0']) - self.assertEqual(node_b.matched_node_link, ['Tensor.a.0']) - diff --git a/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/compare/test_mode_adapter.py b/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/compare/test_mode_adapter.py deleted file mode 100644 index da76d8e0d5..0000000000 --- a/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/compare/test_mode_adapter.py +++ /dev/null @@ -1,99 +0,0 @@ -import json -import unittest -from unittest.mock import patch, MagicMock -from msprobe.pytorch.visualization.compare.mode_adapter import ModeAdapter -from msprobe.pytorch.visualization.graph.base_node import BaseNode, NodeOp -from msprobe.pytorch.visualization.utils import GraphConst, ToolTip -from msprobe.core.common.const import CompareConst - - -class TestModeAdapter(unittest.TestCase): - - def setUp(self): - self.node_op = NodeOp.module - self.node_id = "node_1" - self.node = BaseNode(self.node_op, self.node_id) - self.compare_mode = GraphConst.REAL_DATA_COMPARE - self.adapter = ModeAdapter(self.compare_mode) - self.compare_data_dict = [{}, {}] - - def test_add_md5_compare_data(self): - node_data = {'md5_key': 'some_md5_value'} - compare_data_dict = {'md5_key': 'expected_md5_value'} - precision_index = ModeAdapter._add_md5_compare_data(node_data, compare_data_dict) - self.assertEqual(precision_index, 0) - - @patch('msprobe.pytorch.visualization.compare.mode_adapter.ModeAdapter') - def test_parse_result(self, mock_mode_adapter): - mock_mode_adapter._add_summary_compare_data.return_value = 0.5 - self.adapter.compare_mode = GraphConst.SUMMARY_COMPARE - precision_index, other_dict = self.adapter.parse_result(self.node, self.compare_data_dict) - self.assertEqual(precision_index, 0.5) - self.assertEqual(other_dict, {}) - - mock_mode_adapter._add_md5_compare_data.return_value = 1 - self.adapter.compare_mode = GraphConst.MD5_COMPARE - precision_index, other_dict = self.adapter.parse_result(self.node, self.compare_data_dict) - self.assertEqual(precision_index, 1) - self.assertEqual(other_dict, {'Result': 'pass'}) - - mock_mode_adapter._add_real_compare_data.return_value = 0.6 - self.adapter.compare_mode = GraphConst.REAL_DATA_COMPARE - precision_index, other_dict = self.adapter.parse_result(self.node, self.compare_data_dict) - self.assertEqual(precision_index, 0.0) - self.assertEqual(other_dict, {}) - - def test_prepare_real_data(self): - self.adapter.is_real_data_compare = MagicMock(return_value=True) - result = self.adapter.prepare_real_data(self.node) - self.assertTrue(result) - - self.adapter.is_real_data_compare = MagicMock(return_value=False) - result = self.adapter.prepare_real_data(self.node) - self.assertFalse(result) - - def test_compare_mode_methods(self): - self.adapter.compare_mode = GraphConst.SUMMARY_COMPARE - self.assertTrue(self.adapter.is_summary_compare()) - self.assertFalse(self.adapter.is_md5_compare()) - self.assertFalse(self.adapter.is_real_data_compare()) - - def test_add_csv_data(self): - compare_result_list = ['result1', 'result2'] - self.adapter.add_csv_data(compare_result_list) - self.assertEqual(self.adapter.csv_data, compare_result_list) - - def test_add_error_key(self): - node_data = {'key': {}} - self.adapter.compare_mode = GraphConst.REAL_DATA_COMPARE - self.adapter.add_error_key(node_data) - self.assertEqual(node_data['key'][GraphConst.ERROR_KEY], - [CompareConst.ONE_THOUSANDTH_ERR_RATIO, CompareConst.FIVE_THOUSANDTHS_ERR_RATIO]) - node_data = {'key': {}} - self.adapter.compare_mode = GraphConst.SUMMARY_COMPARE - self.adapter.add_error_key(node_data) - self.assertEqual(node_data['key'][GraphConst.ERROR_KEY], - [CompareConst.MAX_RELATIVE_ERR, CompareConst.MIN_RELATIVE_ERR, - CompareConst.MEAN_RELATIVE_ERR, CompareConst.NORM_RELATIVE_ERR]) - - def test_get_tool_tip(self): - self.adapter.compare_mode = GraphConst.MD5_COMPARE - tips = self.adapter.get_tool_tip() - self.assertEqual(tips, json.dumps({'md5': ToolTip.MD5})) - - self.adapter.compare_mode = GraphConst.SUMMARY_COMPARE - tips = self.adapter.get_tool_tip() - self.assertEqual(tips, json.dumps({ - CompareConst.MAX_DIFF: ToolTip.MAX_DIFF, - CompareConst.MIN_DIFF: ToolTip.MIN_DIFF, - CompareConst.MEAN_DIFF: ToolTip.MEAN_DIFF, - CompareConst.NORM_DIFF: ToolTip.NORM_DIFF})) - - self.adapter.compare_mode = GraphConst.REAL_DATA_COMPARE - tips = self.adapter.get_tool_tip() - self.assertEqual(tips, json.dumps({ - CompareConst.ONE_THOUSANDTH_ERR_RATIO: ToolTip.ONE_THOUSANDTH_ERR_RATIO, - CompareConst.FIVE_THOUSANDTHS_ERR_RATIO: ToolTip.FIVE_THOUSANDTHS_ERR_RATIO, - CompareConst.COSINE: ToolTip.COSINE, - CompareConst.MAX_ABS_ERR: ToolTip.MAX_ABS_ERR, - CompareConst.MAX_RELATIVE_ERR: ToolTip.MAX_RELATIVE_ERR})) diff --git a/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/graph/test_base_node.py b/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/graph/test_base_node.py deleted file mode 100644 index 3f0f12582a..0000000000 --- a/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/graph/test_base_node.py +++ /dev/null @@ -1,76 +0,0 @@ -import unittest -from unittest.mock import patch -from msprobe.pytorch.visualization.graph.base_node import BaseNode, NodeOp -from msprobe.pytorch.visualization.utils import GraphConst - - -class TestBaseNode(unittest.TestCase): - - def setUp(self): - self.node_op = NodeOp.module - self.node_id = "node_1" - self.up_node = BaseNode(self.node_op, "up_node_1") - self.node = BaseNode(self.node_op, self.node_id, self.up_node) - - def test_init_and_str(self): - self.assertEqual(self.node.op, self.node_op) - self.assertEqual(self.node.id, self.node_id) - self.assertEqual(str(self.node), 'id:\tnode_1') - - def test_eq(self): - other_node = BaseNode(self.node_op, self.node_id, self.up_node) - self.assertEqual(self.node, other_node) - - def test_get_suggestions(self): - self.node.get_suggestions() - self.assertIn(GraphConst.SUGGEST_KEY, self.node.suggestions) - - node = BaseNode(NodeOp.function_api, "up_node_1") - node.get_suggestions() - self.assertIn(GraphConst.SUGGEST_KEY, node.suggestions) - - def test_set_input_output(self): - input_data = {'input1': 'value1'} - output_data = {'output1': 'value2'} - self.node.set_input_output(input_data, output_data) - self.assertEqual(self.node.input_data, input_data) - self.assertEqual(self.node.output_data, output_data) - - def test_add_upnode(self): - self.node = BaseNode(self.node_op, self.node_id) - new_up_node = BaseNode(self.node_op, "new_up_node_1") - self.node.add_upnode(new_up_node) - self.assertEqual(self.node.upnode, new_up_node) - self.assertIn(self.node, new_up_node.subnodes) - - def test_add_link(self): - other_node = BaseNode(self.node_op, "other_node_1") - ancestors = ['a1', 'a2'] - self.node.add_link(other_node, ancestors) - self.assertEqual(self.node.matched_node_link, ancestors) - self.assertEqual(other_node.matched_node_link, ancestors) - - def test_to_dict(self): - expected_result = { - 'id': self.node_id, - 'node_type': self.node_op.value, - 'data': {}, - 'output_data': {}, - 'input_data': {}, - 'upnode': self.up_node.id, - 'subnodes': [], - 'matched_node_link': [], - 'suggestions': {}, - 'stack_info': [] - } - self.assertEqual(self.node.to_dict(), expected_result) - - def test_get_ancestors(self): - expected_ancestors = ['up_node_1'] - self.assertEqual(self.node.get_ancestors(), expected_ancestors) - - @patch('msprobe.pytorch.visualization.builder.msprobe_adapter.compare_mapping_data') - def test_compare_mapping_node(self, mock_compare_mapping_data): - mock_compare_mapping_data.return_value = True - result = self.node.compare_mapping_node(BaseNode(NodeOp.function_api, "up_node_1")) - self.assertTrue(result) diff --git a/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/graph/test_graph.py b/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/graph/test_graph.py deleted file mode 100644 index e7a55bb36e..0000000000 --- a/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/graph/test_graph.py +++ /dev/null @@ -1,102 +0,0 @@ -import unittest -from unittest.mock import MagicMock -from msprobe.pytorch.visualization.graph.graph import Graph, NodeOp -from msprobe.pytorch.visualization.graph.base_node import BaseNode -from msprobe.pytorch.visualization.utils import GraphConst - - -class TestGraph(unittest.TestCase): - - def setUp(self): - self.graph = Graph("model_name") - self.node_id = "node_id" - self.node_op = NodeOp.module - - def test_add_node_and_get_node(self): - self.graph.add_node(self.node_op, self.node_id) - node = self.graph.get_node(self.node_id) - self.assertIsNotNone(node) - self.assertIn(self.node_id, self.graph.node_map) - - node_id = "api" - graph = Graph("model_name") - for i in range(0, 9): - graph.add_node(NodeOp.function_api, node_id, id_accumulation=True) - self.assertEqual(len(graph.node_map), 10) - self.assertIn("api.0", graph.node_map) - self.assertIn("api.8", graph.node_map) - self.assertNotIn("api", graph.node_map) - - def test_to_dict(self): - self.graph.add_node(self.node_op, self.node_id) - result = self.graph.to_dict() - self.assertEqual(result[GraphConst.JSON_ROOT_KEY], "model_name") - self.assertIn(self.node_id, result[GraphConst.JSON_NODE_KEY]) - - def test_str(self): - self.graph.add_node(self.node_op, self.node_id) - expected_str = f'{self.node_id}' - self.assertIn(expected_str, str(self.graph)) - - def test_match(self): - graph_a = Graph("model_name_a") - graph_b = Graph("model_name_b") - node_a = BaseNode(self.node_op, self.node_id) - graph_a.add_node(NodeOp.module, "node_id_a") - graph_b.add_node(NodeOp.module, "node_id_b") - matched_node, ancestors = Graph.match(graph_a, node_a, graph_b) - self.assertIsNone(matched_node) - self.assertEqual(ancestors, []) - - graph_b.add_node(NodeOp.module, "node_id_a") - graph_a.add_node(NodeOp.module, "node_id_a_1", graph_a.get_node("node_id_a")) - graph_b.add_node(NodeOp.module, "node_id_a_1", graph_a.get_node("node_id_a")) - matched_node, ancestors = Graph.match(graph_a, graph_a.get_node("node_id_a_1"), graph_b) - self.assertIsNotNone(matched_node) - self.assertEqual(ancestors, ['node_id_a']) - - def test_dfs(self): - graph = Graph("model_name") - graph.add_node(NodeOp.module, "node_a") - graph.add_node(NodeOp.module, "node_b") - node_a = BaseNode(self.node_op, self.node_id) - result = {} - graph.dfs(node_a, result) - self.assertEqual(result, {'node_id': {'id': 'node_id', 'node_type': 0, 'data': {}, - 'output_data': {}, 'input_data': {}, 'upnode': 'None', 'subnodes': [], - 'matched_node_link': [], 'suggestions': {}}}) - - def test_split_nodes_by_micro_step(self): - nodes = [BaseNode(NodeOp.module, 'a.0'), BaseNode(NodeOp.module, 'b.0'), - BaseNode(NodeOp.api_collection, 'apis.0'), BaseNode(NodeOp.module, 'a.1'), - BaseNode(NodeOp.module, 'b.1'), BaseNode(NodeOp.api_collection, 'apis.1')] - result = Graph.split_nodes_by_micro_step(nodes) - self.assertEqual(len(result), 2) - self.assertEqual(len(result[0]), 3) - - def test_paging_by_micro_step(self): - nodes = [BaseNode(NodeOp.module, 'a.0'), BaseNode(NodeOp.module, 'b.0'), - BaseNode(NodeOp.api_collection, 'apis.0'), BaseNode(NodeOp.module, 'a.1'), - BaseNode(NodeOp.module, 'b.1'), BaseNode(NodeOp.api_collection, 'apis.1')] - - graph = Graph('Model1') - graph.root.subnodes = nodes - graph_other = Graph('Model2') - graph_other.root.subnodes = nodes - - result = graph.paging_by_micro_step(graph_other) - self.assertEqual(result, 2) - self.assertEqual(graph.root.subnodes[0].micro_step_id, 0) - self.assertEqual(graph_other.root.subnodes[0].micro_step_id, 0) - - def test_mapping_match(self): - mapping_config = MagicMock() - graph_a = Graph("model_name_a") - graph_b = Graph("model_name_b") - graph_a.add_node(NodeOp.module, "a1", BaseNode(NodeOp.module, "root")) - graph_b.add_node(NodeOp.module, "b1", BaseNode(NodeOp.module, "root")) - mapping_config.get_mapping_string.return_value = "b1" - node_b, ancestors_n, ancestors_b = Graph.mapping_match(graph_a.get_node("a1"), graph_b, mapping_config) - self.assertIsNotNone(node_b) - self.assertEqual(ancestors_n, ["root"]) - self.assertEqual(ancestors_b, ["root"]) diff --git a/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/graph/test_node_colors.py b/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/graph/test_node_colors.py deleted file mode 100644 index 0be05586b1..0000000000 --- a/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/graph/test_node_colors.py +++ /dev/null @@ -1,67 +0,0 @@ -import unittest -from msprobe.pytorch.visualization.graph.node_colors import NodeColors, SUMMARY_DESCRIPTION, REAL_DATA_DESCRIPTION, \ - NOT_MATCHED -from msprobe.pytorch.visualization.utils import GraphConst - - -class TestNodeColors(unittest.TestCase): - - def test_get_info_by_mode(self): - node_yellow = NodeColors.YELLOW_1 - summary_info = node_yellow.get_info_by_mode(GraphConst.SUMMARY_COMPARE) - self.assertEqual(summary_info[GraphConst.VALUE], [0, 0.2]) - self.assertEqual(summary_info[GraphConst.DESCRIPTION], SUMMARY_DESCRIPTION) - node_grey = NodeColors.GREY - md5_info = node_grey.get_info_by_mode(GraphConst.MD5_COMPARE) - self.assertEqual(md5_info[GraphConst.VALUE], []) - self.assertEqual(md5_info[GraphConst.DESCRIPTION], NOT_MATCHED) - node_red = NodeColors.RED - real_info = node_red.get_info_by_mode(GraphConst.REAL_DATA_COMPARE) - self.assertEqual(real_info[GraphConst.VALUE], [0.2, 1]) - self.assertEqual(real_info[GraphConst.DESCRIPTION], REAL_DATA_DESCRIPTION) - none_info = node_yellow.get_info_by_mode("non_existent_mode") - self.assertEqual(none_info, {}) - - def test_get_node_colors(self): - # 测试获取所有颜色信息的函数 - mode = GraphConst.SUMMARY_COMPARE - colors_info = NodeColors.get_node_colors(mode) - self.assertIn("#FFFCF3", colors_info) - self.assertIn("#FFEDBE", colors_info) - self.assertIn("#FFDC7F", colors_info) - self.assertIn("#FFC62E", colors_info) - self.assertIn("#E32020", colors_info) - self.assertIn("#C7C7C7", colors_info) - - # 确保返回的字典具有正确的描述和值范围 - expected_value_range = [0, 0.2] - expected_description = "此节点所有输入输出的统计量相对误差, 值越大代表测量值与标杆值的偏差越大, 相对误差计算方式:|(测量值-标杆值)/标杆值|" - self.assertEqual(colors_info["#FFFCF3"][GraphConst.VALUE], expected_value_range) - self.assertEqual(colors_info["#FFFCF3"][GraphConst.DESCRIPTION], expected_description) - - mode = GraphConst.MD5_COMPARE - colors_info = NodeColors.get_node_colors(mode) - self.assertIn("#FFFCF3", colors_info) - self.assertIn("#C7C7C7", colors_info) - self.assertNotIn("#FFDC7F", colors_info) - - expected_value_range = [1, 1] - expected_description = "与标杆相比, 此节点所有输入输出的md5值相同" - self.assertEqual(colors_info["#FFFCF3"][GraphConst.VALUE], expected_value_range) - self.assertEqual(colors_info["#FFFCF3"][GraphConst.DESCRIPTION], expected_description) - - def test_get_node_error_status(self): - # 测试错误状态判断功能 - mode = GraphConst.SUMMARY_COMPARE - value0 = 0 - value1 = 0.25 - value2 = 0.55 - value3 = 111 - self.assertFalse(NodeColors.get_node_error_status(mode, value0)) - self.assertFalse(NodeColors.get_node_error_status(mode, value1)) - self.assertTrue(NodeColors.get_node_error_status(mode, value2)) - self.assertTrue(NodeColors.get_node_error_status(mode, value3)) - - -if __name__ == '__main__': - unittest.main() diff --git a/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/graph/test_node_op.py b/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/graph/test_node_op.py deleted file mode 100644 index 1a340ac8b3..0000000000 --- a/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/graph/test_node_op.py +++ /dev/null @@ -1,28 +0,0 @@ -import unittest -from msprobe.pytorch.visualization.graph.node_op import NodeOp - - -class TestNodeOp(unittest.TestCase): - - def test_get_node_op_valid(self): - node_name = "ModuleTest" - self.assertEqual(NodeOp.get_node_op(node_name), NodeOp.module) - - def test_get_node_op_invalid(self): - node_name = "InvalidNodeName" - with self.assertRaises(Exception): - NodeOp.get_node_op(node_name) - - def test_get_node_op_all(self): - test_cases = [ - ("ModuleTest", NodeOp.module), - ("TensorTest", NodeOp.function_api), - ("TorchTest", NodeOp.function_api), - ("FunctionalTest", NodeOp.function_api), - ("NPUTest", NodeOp.function_api), - ("VFTest", NodeOp.function_api), - ("DistributedTest", NodeOp.function_api), - ("AtenTest", NodeOp.function_api) - ] - for node_name, expected_op in test_cases: - self.assertEqual(NodeOp.get_node_op(node_name), expected_op) diff --git a/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/mapping.yaml b/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/mapping.yaml deleted file mode 100644 index 8b2f85ebf8..0000000000 --- a/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/mapping.yaml +++ /dev/null @@ -1,2 +0,0 @@ -- vision_model: "language_model.vision_encoder" -- vision_projection: "language_model.projection" \ No newline at end of file diff --git a/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/test_mapping_config.py b/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/test_mapping_config.py deleted file mode 100644 index 010a4f6861..0000000000 --- a/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/test_mapping_config.py +++ /dev/null @@ -1,52 +0,0 @@ -import os -import unittest -from msprobe.pytorch.visualization.mapping_config import MappingConfig - - -class TestMappingConfig(unittest.TestCase): - - def setUp(self): - self.yaml_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "mapping.yaml") - - def test_validate(self): - with self.assertRaises(ValueError): - MappingConfig.validate(123, "some value") - with self.assertRaises(ValueError): - MappingConfig.validate("some key", 456) - self.assertEqual(MappingConfig.validate("key", "value"), "value") - - def test_convert_to_regex(self): - regex = MappingConfig.convert_to_regex("hello{world}") - self.assertEqual(regex, ".*hello\\{world\\}.*") - - def test_replace_parts(self): - result = MappingConfig._replace_parts('hello world', 'world', 'everyone') - self.assertEqual(result, 'hello everyone') - result = MappingConfig._replace_parts('radio_model.layers.0.input_norm', 'radio_model.layers.{}.input_norm', - 'radio_model.transformer.layers.{}.input_layernorm') - self.assertEqual(result, 'radio_model.transformer.layers.0.input_layernorm') - - def test_get_mapping_string(self): - mc = MappingConfig(self.yaml_path) - mc.classify_config = { - 'category1': [('category1.key1', 'replacement1')], - 'category2': [('category2.key1', 'replacement2')] - } - result = mc.get_mapping_string("some category1.key1 text") - self.assertEqual(result, "some replacement1 text") - - def test_long_string(self): - long_string = "x" * (MappingConfig.MAX_STRING_LEN + 1) - mc = MappingConfig(self.yaml_path) - result = mc.get_mapping_string(long_string) - self.assertEqual(result, long_string) - - def test__classify_and_sort_keys(self): - mc = MappingConfig(self.yaml_path) - result = mc._classify_and_sort_keys() - self.assertEqual(result, {'vision_model': [('vision_model', 'language_model.vision_encoder')], - 'vision_projection': [('vision_projection', 'language_model.projection')]}) - - -if __name__ == '__main__': - unittest.main() diff --git a/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/test_utils.py b/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/test_utils.py deleted file mode 100644 index 56493235cd..0000000000 --- a/debug/accuracy_tools/msprobe/test/pytorch_ut/visualization/test_utils.py +++ /dev/null @@ -1,27 +0,0 @@ -import os -import unittest -from msprobe.pytorch.visualization.utils import (load_json_file, load_data_json_file, str2float) - - -class TestMappingConfig(unittest.TestCase): - - def setUp(self): - self.yaml_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "mapping.yaml") - - def test_load_json_file(self): - result = load_json_file(self.yaml_path) - self.assertEqual(result, {}) - - def test_load_data_json_file(self): - result = load_data_json_file(self.yaml_path) - self.assertEqual(result, {}) - - def test_str2float(self): - result = str2float('23.4%') - self.assertAlmostEqual(result, 0.234) - result = str2float('2.3.4%') - self.assertAlmostEqual(result, 0) - - -if __name__ == '__main__': - unittest.main() -- Gitee