From 208f460c37efe048eaa6de76002741513bb6b31b Mon Sep 17 00:00:00 2001 From: hekunkun Date: Thu, 25 Jan 2024 08:54:35 +0000 Subject: [PATCH] =?UTF-8?q?=E5=9B=9E=E9=80=80=20'Pull=20Request=20!565=20:?= =?UTF-8?q?=20=E3=80=90Feature=E3=80=91Ptdbg=E6=94=AF=E6=8C=81NPU/NPU?= =?UTF-8?q?=E7=AE=97=E5=AD=90=E7=BA=A7=E6=AF=94=E5=AF=B9=EF=BC=88=E9=92=88?= =?UTF-8?q?=E5=AF=B9=E7=A1=AE=E5=AE=9A=E6=80=A7=E8=AE=A1=E7=AE=97=EF=BC=89?= =?UTF-8?q?'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ptdbg_ascend/parse_tool/lib/compare.py | 102 ------------------ .../ptdbg_ascend/parse_tool/lib/config.py | 4 - .../parse_tool/lib/interactive_cli.py | 6 +- .../ptdbg_ascend/parse_tool/lib/parse_tool.py | 49 --------- .../ptdbg_ascend/parse_tool/lib/utils.py | 84 +-------------- 5 files changed, 4 insertions(+), 241 deletions(-) diff --git a/debug/accuracy_tools/ptdbg_ascend/src/python/ptdbg_ascend/parse_tool/lib/compare.py b/debug/accuracy_tools/ptdbg_ascend/src/python/ptdbg_ascend/parse_tool/lib/compare.py index 4119a5485..ba8692578 100644 --- a/debug/accuracy_tools/ptdbg_ascend/src/python/ptdbg_ascend/parse_tool/lib/compare.py +++ b/debug/accuracy_tools/ptdbg_ascend/src/python/ptdbg_ascend/parse_tool/lib/compare.py @@ -16,7 +16,6 @@ """ import os -import time import numpy as np from .utils import Util from .config import Const @@ -149,104 +148,3 @@ class Compare: err_percent = float(err_cnt / total_cnt) self.util.print(self.util.create_columns([err_table, top_table])) return total_cnt, all_close, cos_sim, err_percent - - def _compare_npy(self, file, bench_file, output_path): - data = np.load(file) - bench_data = np.load(bench_file) - shape, dtype = data.shape, data.dtype - bench_shape, bench_dtype = bench_data.shape, bench_data.dtype - filename = os.path.basename(file) - bench_filename = os.path.basename(bench_file) - if shape != bench_shape or dtype != bench_dtype: - self.log.error( - "Shape or dtype between two npy files is inconsistent. Please check the two files." - "File 1: %s, file 2: %s", file, bench_file) - self.util.deal_with_dir_or_file_inconsistency(output_path) - return - md5_consistency = False - if self.util.get_md5_for_numpy(data) == self.util.get_md5_for_numpy(bench_data): - md5_consistency = True - data_mean = np.mean(data) - bench_data_mean = np.mean(bench_data) - abs_error = np.abs(data - bench_data) - bench_data = self.util.deal_with_value_if_has_zero(bench_data) - rel_error = np.abs(abs_error / bench_data) - abs_diff_max = abs_error.max() - rel_diff_max = np.max(rel_error) - compare_result = [[filename, bench_filename, data_mean, bench_data_mean, md5_consistency, abs_diff_max, - rel_diff_max]] - self.util.write_csv(compare_result, output_path) - - def compare_all_file_in_directory(self, my_dump_dir, golden_dump_dir, output_path): - if not (self.util.is_subdir_count_equal(my_dump_dir, golden_dump_dir) - and self.util.check_npy_files_valid_in_dir(my_dump_dir) - and self.util.check_npy_files_valid_in_dir(golden_dump_dir)): - self.log.error( - "Top level(Npy files level) directory structure is inconsistent. Please check the two directory.") - self.util.deal_with_dir_or_file_inconsistency(output_path) - return - my_npy_files = self.util.get_sorted_files_names(my_dump_dir) - golden_npy_files = self.util.get_sorted_files_names(golden_dump_dir) - for my_npy_file_name, golden_npy_file_name in zip(my_npy_files, golden_npy_files): - my_npy_path = os.path.join(my_dump_dir, my_npy_file_name) - golden_npy_path = os.path.join(golden_dump_dir, golden_npy_file_name) - self._compare_npy(my_npy_path, golden_npy_path, output_path) - - def compare_timestamp_directory(self, my_dump_dir, golden_dump_dir, output_path): - if not self.util.is_subdir_count_equal(my_dump_dir, golden_dump_dir): - self.log.error( - "Second level(Timestamp level) directory structure is inconsistent. Please check the two directory.") - self.util.deal_with_dir_or_file_inconsistency(output_path) - return - my_ordered_subdirs = self.util.get_sorted_subdirectories_names(my_dump_dir) - golden_ordered_subdirs = self.util.get_sorted_subdirectories_names(golden_dump_dir) - for my_subdir_name, golden_subdir_name in zip(my_ordered_subdirs, golden_ordered_subdirs): - my_subdir_path = os.path.join(my_dump_dir, my_subdir_name) - golden_subdir_path = os.path.join(golden_dump_dir, golden_subdir_name) - self.compare_all_file_in_directory(my_subdir_path, golden_subdir_path, output_path) - - def compare_converted_dir(self, my_dump_dir, golden_dump_dir, output_dir): - if not self.util.is_subdir_count_equal(my_dump_dir, golden_dump_dir): - self.log.error( - "Top level(Opname level) directory structure is inconsistent. Please check the two directory.") - return - timestamp = int(time.time()) - output_file_name = f"batch_compare_{timestamp}.csv" - output_path = os.path.join(output_dir, output_file_name) - title_rows = [[ - "NPU File Name", - "Bench File Name", - "Mean", - "Bench Mean", - "Md5 Consistency", - "Max Abs Error", - "Max Relative Error" - ]] - self.util.write_csv(title_rows, output_path) - - my_ordered_subdirs = self.util.get_sorted_subdirectories_names(my_dump_dir) - golden_ordered_subdirs = self.util.get_sorted_subdirectories_names(golden_dump_dir) - for my_subdir_name, golden_subdir_name in zip(my_ordered_subdirs, golden_ordered_subdirs): - if not my_subdir_name == golden_subdir_name: - self.log.error( - "Top level(Opname level) directory structure is inconsistent. Please check the two directory.") - self.util.deal_with_dir_or_file_inconsistency(output_path) - return - my_subdir_path = os.path.join(my_dump_dir, my_subdir_name) - golden_subdir_path = os.path.join(golden_dump_dir, golden_subdir_name) - self.compare_timestamp_directory(my_subdir_path, golden_subdir_path, output_path) - self.log.info("Compare result is saved in : %s", output_path) - - def convert_api_dir_to_npy(self, dump_dir, param, output_dir, msaccucmp_path): - dump_dir = self.util.path_strip(dump_dir) - for root, dirs, files in os.walk(dump_dir): - for file in files: - file_path = os.path.join(root, file) - file_name = os.path.basename(file_path) - parts = file_name.split(".") - if len(parts) < 5: - continue - op_name = parts[1] - timestamp = parts[-1] - output_path = os.path.join(output_dir, op_name, timestamp) - self.convert_dump_to_npy(file_path, param, output_path, msaccucmp_path) diff --git a/debug/accuracy_tools/ptdbg_ascend/src/python/ptdbg_ascend/parse_tool/lib/config.py b/debug/accuracy_tools/ptdbg_ascend/src/python/ptdbg_ascend/parse_tool/lib/config.py index 97de8572c..9cf479d64 100644 --- a/debug/accuracy_tools/ptdbg_ascend/src/python/ptdbg_ascend/parse_tool/lib/config.py +++ b/debug/accuracy_tools/ptdbg_ascend/src/python/ptdbg_ascend/parse_tool/lib/config.py @@ -16,7 +16,6 @@ """ import os -import numpy as np class Const: @@ -28,8 +27,6 @@ class Const: DATA_ROOT_DIR = os.path.join(ROOT_DIR, 'parse_data') DUMP_CONVERT_DIR = os.path.join(DATA_ROOT_DIR, 'dump_convert') COMPARE_DIR = os.path.join(DATA_ROOT_DIR, 'compare_result') - BATCH_DUMP_CONVERT_DIR = os.path.join(DATA_ROOT_DIR, 'batch_dump_convert') - BATCH_COMPARE_DIR = os.path.join(DATA_ROOT_DIR, 'batch_compare_result') OFFLINE_DUMP_CONVERT_PATTERN = \ r"^([A-Za-z0-9_-]+)\.([A-Za-z0-9_-]+)\.([0-9]+)(\.[0-9]+)?\.([0-9]{1,255})" \ r"\.([a-z]+)\.([0-9]{1,255})(\.[x0-9]+)?\.npy$" @@ -41,7 +38,6 @@ class Const: FILE_PATTERN = r'^[a-zA-Z0-9_./-]+$' ONE_GB = 1 * 1024 * 1024 * 1024 TEN_GB = 10 * 1024 * 1024 * 1024 - FLOAT_TYPE = [np.half, np.single, float, np.double, np.float64, np.longdouble, np.float32, np.float16] HEADER = r""" ____ / __ \____ ______________ / /_/ / __ `/ ___/ ___/ _ \ diff --git a/debug/accuracy_tools/ptdbg_ascend/src/python/ptdbg_ascend/parse_tool/lib/interactive_cli.py b/debug/accuracy_tools/ptdbg_ascend/src/python/ptdbg_ascend/parse_tool/lib/interactive_cli.py index d645eb453..df1de148e 100644 --- a/debug/accuracy_tools/ptdbg_ascend/src/python/ptdbg_ascend/parse_tool/lib/interactive_cli.py +++ b/debug/accuracy_tools/ptdbg_ascend/src/python/ptdbg_ascend/parse_tool/lib/interactive_cli.py @@ -52,7 +52,7 @@ class InteractiveCli(cmd.Cmd): self.util.execute_command(line) def do_vc(self, line=""): - self.parse_tool.do_compare_converted_dir(self._parse_argv(line)) + self.parse_tool.do_vector_compare(self._parse_argv(line)) def do_dc(self, line=""): self.parse_tool.do_convert_dump(self._parse_argv(line)) @@ -65,7 +65,3 @@ class InteractiveCli(cmd.Cmd): def do_cn(self, line=''): self.parse_tool.do_compare_data(self._parse_argv(line)) - - def do_cad(self, line=''): - self.parse_tool.do_convert_api_dir(self._parse_argv(line)) - diff --git a/debug/accuracy_tools/ptdbg_ascend/src/python/ptdbg_ascend/parse_tool/lib/parse_tool.py b/debug/accuracy_tools/ptdbg_ascend/src/python/ptdbg_ascend/parse_tool/lib/parse_tool.py index 037dd3965..2dbda3078 100644 --- a/debug/accuracy_tools/ptdbg_ascend/src/python/ptdbg_ascend/parse_tool/lib/parse_tool.py +++ b/debug/accuracy_tools/ptdbg_ascend/src/python/ptdbg_ascend/parse_tool/lib/parse_tool.py @@ -140,52 +140,3 @@ class ParseTool: self.util.check_path_format(args.my_dump_path, Const.NPY_SUFFIX) self.util.check_path_format(args.golden_dump_path, Const.NPY_SUFFIX) self.compare.compare_data(args.my_dump_path, args.golden_dump_path, args.save, args.rtol, args.atol, args.count) - - @catch_exception - def do_compare_converted_dir(self, argv=None): - """compare two dir""" - parser = argparse.ArgumentParser() - parser.add_argument( - "-m", "--my_dump_path", dest="my_dump_path", default=None, - help=" my dump path, the data compared with golden data", - required=True - ) - parser.add_argument( - "-g", "--golden_dump_path", dest="golden_dump_path", default=None, - help=" the golden dump data path", - required=True - ) - parser.add_argument( - '-out', '--output_path', dest='output_path', required=False, default=None, help='output path') - args = parser.parse_args(argv) - self.util.check_path_valid(args.my_dump_path) - self.util.check_path_valid(args.golden_dump_path) - my_dump_dir = self.util.path_strip(args.my_dump_path) - golden_dump_dir = self.util.path_strip(args.golden_dump_path) - if my_dump_dir == golden_dump_dir: - self.util.log.error("My directory path and golden directory path is same. Please check parameter" - " '-m' and '-g'.") - raise ParseException("My directory path and golden directory path is same.") - output_path = self.util.path_strip(args.output_path) if args.output_path else Const.BATCH_COMPARE_DIR - self.compare.compare_converted_dir(my_dump_dir, golden_dump_dir, output_path) - - @catch_exception - def do_convert_api_dir(self, argv=None): - parser = argparse.ArgumentParser() - parser.add_argument( - "-m", "--my_dump_path", dest="my_dump_path", default=None, - help=" my dump path, the data need to convert to npy files.", - required=True - ) - parser.add_argument( - '-out', '--output_path', dest='output_path', required=False, default=None, help='output path') - parser.add_argument( - "-asc", "--msaccucmp_path", dest="msaccucmp_path", default=None, - help=" the msaccucmp.py file path", required=False) - args = parser.parse_args(argv) - self.util.check_path_valid(args.my_dump_path) - self.util.check_files_in_path(args.my_dump_path) - output_path = self.util.path_strip(args.output_path) if args.output_path else Const.BATCH_DUMP_CONVERT_DIR - msaccucmp_path = self.util.path_strip( - args.msaccucmp_path) if args.msaccucmp_path else Const.MS_ACCU_CMP_PATH - self.compare.convert_api_dir_to_npy(args.my_dump_path, None, output_path, msaccucmp_path) diff --git a/debug/accuracy_tools/ptdbg_ascend/src/python/ptdbg_ascend/parse_tool/lib/utils.py b/debug/accuracy_tools/ptdbg_ascend/src/python/ptdbg_ascend/parse_tool/lib/utils.py index 90272d5eb..2d512224f 100644 --- a/debug/accuracy_tools/ptdbg_ascend/src/python/ptdbg_ascend/parse_tool/lib/utils.py +++ b/debug/accuracy_tools/ptdbg_ascend/src/python/ptdbg_ascend/parse_tool/lib/utils.py @@ -16,20 +16,16 @@ """ import logging import os -import io import re import sys import subprocess -import hashlib -import csv import numpy as np from .config import Const from .file_desc import DumpDecodeFileDesc, FileDesc from .parse_exception import ParseException -from ...common.file_check_util import change_mode, check_other_user_writable, \ +from ...common.file_check_util import change_mode, check_other_user_writable,\ check_path_executable, check_path_owner_consistent from ...common.file_check_util import FileCheckConst -from ...common.file_check_util import FileOpen try: from rich.traceback import install @@ -37,7 +33,6 @@ try: from rich.table import Table from rich import print as rich_print from rich.columns import Columns - install() except ImportError as err: install = None @@ -45,8 +40,7 @@ except ImportError as err: Table = None Columns = None rich_print = None - print( - "[Warning] Failed to import rich, Some features may not be available. Please run 'pip install rich' to fix it.") + print("[Warning] Failed to import rich, Some features may not be available. Please run 'pip install rich' to fix it.") class Util: @@ -132,7 +126,7 @@ class Util: shape, dtype, max_data, min_data, mean = \ self.npy_info(source_data) return \ - '[Shape: %s] [Dtype: %s] [Max: %s] [Min: %s] [Mean: %s]' % (shape, dtype, max_data, min_data, mean) + '[Shape: %s] [Dtype: %s] [Max: %s] [Min: %s] [Mean: %s]' % (shape, dtype, max_data, min_data, mean) def save_npy_to_txt(self, data, dst_file='', align=0): if os.path.exists(dst_file): @@ -195,7 +189,6 @@ class Util: if path.endswith(Const.NPY_SUFFIX) and file_size > Const.TEN_GB: self.log.error('The file {} size is greater than 10GB.'.format(path)) raise ParseException(ParseException.PARSE_INVALID_PATH_ERROR) - return True def check_files_in_path(self, path): if os.path.isdir(path) and len(os.listdir(path)) == 0: @@ -258,74 +251,3 @@ class Util: if not re.match(Const.FILE_PATTERN, param): self.log.error('The parameter {} contains special characters.'.format(param)) raise ParseException(ParseException.PARSE_INVALID_PARAM_ERROR) - - def get_subdir_count(self, directory): - subdir_count = 0 - for root, dirs, files in os.walk(directory): - subdir_count += len(dirs) - break - return subdir_count - - def get_subfiles_count(self, directory): - file_count = 0 - for root, dirs, files in os.walk(directory): - file_count += len(files) - return file_count - - def is_subdir_count_equal(self, dir1, dir2): - dir1_count = self.get_subdir_count(dir1) - dir2_count = self.get_subdir_count(dir2) - return dir1_count == dir2_count - - def get_sorted_subdirectories_names(self, directory): - subdirectories = [] - for item in os.listdir(directory): - item_path = os.path.join(directory, item) - if os.path.isdir(item_path): - subdirectories.append(item) - return sorted(subdirectories) - - def get_sorted_files_names(self, directory): - files = [] - for item in os.listdir(directory): - item_path = os.path.join(directory, item) - if os.path.isfile(item_path): - files.append(item) - return sorted(files) - - def check_npy_files_valid_in_dir(self, dir_path): - for file_name in os.listdir(dir_path): - file_path = os.path.join(dir_path, file_name) - if not self.check_path_valid(file_path): - return False - _, file_extension = os.path.splitext(file_path) - if not file_extension == '.npy': - return False - return True - - def get_md5_for_numpy(self, obj): - np_bytes = obj.tobytes() - md5_hash = hashlib.md5(np_bytes) - return md5_hash.hexdigest() - - def write_csv(self, data, filepath): - with FileOpen(filepath, 'a') as f: - writer = csv.writer(f) - writer.writerows(data) - - def deal_with_dir_or_file_inconsistency(self, output_path): - if os.path.exists(output_path): - os.remove(output_path) - raise ParseException("Inconsistent directory structure or file.") - - def deal_with_value_if_has_zero(self, data): - if data.dtype in Const.FLOAT_TYPE: - zero_mask = (data == 0) - # 给0的地方加上eps防止除0 - data[zero_mask] += np.finfo(data.dtype).eps - else: - # int type + float eps 会报错,所以这里要强转 - data = data.astype(float) - zero_mask = (data == 0) - data[zero_mask] += np.finfo(float).eps - return data -- Gitee