diff --git a/profiler/advisor/advisor_backend/compute_advice/compute_advice_base.py b/profiler/advisor/advisor_backend/compute_advice/compute_advice_base.py index 811cce84e0d787c1fc71365a73eef0e560f176c4..cca97c1e77739c08d11dbaa9e03494936d16b382 100644 --- a/profiler/advisor/advisor_backend/compute_advice/compute_advice_base.py +++ b/profiler/advisor/advisor_backend/compute_advice/compute_advice_base.py @@ -42,7 +42,8 @@ class ComputeAdviceBase(AdviceBase): if not os.path.exists(self.collection_path): print("[ERROR] Path: {} is not exist.".format(self.collection_path)) return False - if os.path.isdir(self.collection_path) and self.collection_path.endswith("ascend_pt"): + if os.path.isdir(self.collection_path) and \ + (self.collection_path.endswith("ascend_pt") or self.collection_path.endswith("ascend_ms")): self.kernel_details_path = os.path.join(self.collection_path, "ASCEND_PROFILER_OUTPUT", "kernel_details.csv") if not os.path.exists(self.kernel_details_path): diff --git a/profiler/advisor/advisor_backend/timeline_advice/timeline_advice_base.py b/profiler/advisor/advisor_backend/timeline_advice/timeline_advice_base.py index e2aa1e5ae12bf9c03f0e3f163221df08fb20c4a4..0bcf9a8f68787fc42d1ed5f9e34eafd42e5cbb21 100644 --- a/profiler/advisor/advisor_backend/timeline_advice/timeline_advice_base.py +++ b/profiler/advisor/advisor_backend/timeline_advice/timeline_advice_base.py @@ -55,7 +55,8 @@ class TimelineAdviceBase(AdviceBase): if not os.path.exists(self.collection_path): logger.error("Path: %s is not exist.",str(self.collection_path)) return False - if os.path.isdir(self.collection_path) and self.collection_path.endswith("ascend_pt"): + if os.path.isdir(self.collection_path) and \ + (self.collection_path.endswith("ascend_pt") or self.collection_path.endswith("ascend_ms")): self.trace_view_path = os.path.join(self.collection_path, "ASCEND_PROFILER_OUTPUT", "trace_view.json") if not os.path.exists(self.trace_view_path): logger.error("trace_view.json is not exist in the Path: %s."\ diff --git a/profiler/advisor/analyzer/analyzer_controller.py b/profiler/advisor/analyzer/analyzer_controller.py index 4da80e08f46651664818ff90769412175b5a7ee4..d47d943415c28a149ed8e18936e91d80bb13260c 100644 --- a/profiler/advisor/analyzer/analyzer_controller.py +++ b/profiler/advisor/analyzer/analyzer_controller.py @@ -39,6 +39,7 @@ from profiler.advisor.common.enum_params_parser import EnumParamsParser from profiler.advisor.utils.utils import Timer, safe_index_value, safe_division, safe_index, convert_to_int from profiler.advisor.interface.interface import Interface from profiler.cluster_analyse.cluster_data_preprocess.pytorch_data_preprocessor import PytorchDataPreprocessor +from profiler.cluster_analyse.cluster_data_preprocess.mindspore_data_preprocessor import MindsporeDataPreprocessor from profiler.prof_common.path_manager import PathManager from profiler.prof_common.constant import Constant @@ -185,28 +186,6 @@ class AnalyzerController: return True - @staticmethod - def _whether_include_mindspore_prof(profiling_path): - # 暂不支持Mindspore数据,支持后可删除该限制 - ASCEND_MS = "ascend_ms" - - has_ascend_ms_dirs = False - for root, dirs, _ in os.walk(profiling_path): - if root.endswith(ASCEND_MS): - has_ascend_ms_dirs = True - break - for dir_name in dirs: - if dir_name.endswith(ASCEND_MS): - has_ascend_ms_dirs = True - break - if has_ascend_ms_dirs: - break - - if has_ascend_ms_dirs: - logger.error("Advisor does not support data from MindSpore now, existing dirs end with 'ascend_ms'") - return True - - return False @staticmethod def _get_step_rank_for_cluster_statistic_diff(target_cluster_statistic_data, benchmark_cluster_statistic_data, @@ -318,7 +297,8 @@ class AnalyzerController: dimensions: analysis dimension, normally set as Interface.all_dimension, support specific dimension analysis such as ['computation'] or ['computation', 'schedule'] cann_version: cann version of your runtime, inpact on the analysis of affinity api and AICPU operators - torch_version: torch version of your runtime, inpact on the analysis of affinity api + profiling_type: profiling type of your runtime + profiling_version: profiling version of your runtime, inpact on the analysis of affinity api analysis_dimensions: can overwite dimensions. advisor_analyze_processes: number of processes to use while the training params pipeline parallel(pp) >1, can reduce the time of analysis. @@ -646,14 +626,6 @@ class AnalyzerController: logger.error(error_msg) return - # 暂不支持Mindspore数据,支持后可删除该限制 - if self._whether_include_mindspore_prof(profiling_path): - error_msg = f"Got *_ascend_ms dirs from {profiling_path}, skip analysis" - self._update_analysis_process_resp(pid, async_resp, error_msg=error_msg, - status_code=AsyncAnalysisStatus.FAILED_STATUS_CODE, - status=AsyncAnalysisStatus.FAILED) - logger.error(error_msg) - return if benchmark_profiling_path and not self._check_profiling_path_valid(benchmark_profiling_path): error_msg = (f"Got invalid argument '-bp/--benchmark_profiling_path' {benchmark_profiling_path}, " @@ -840,7 +812,16 @@ class AnalyzerController: return False path_list = [os.path.join(profiling_path, dir_name) for dir_name in os.listdir(profiling_path)] ascend_pt_dirs = [path for path in path_list if os.path.isdir(path) and path.endswith("ascend_pt")] - data_processor = PytorchDataPreprocessor(ascend_pt_dirs) + ascend_ms_dirs = [path for path in path_list if os.path.isdir(path) and path.endswith("ascend_ms")] + if ascend_ms_dirs and ascend_pt_dirs: + logger.error("Cannot analyze pytorch and mindspore meantime.") + return False + if not ascend_pt_dirs and not ascend_ms_dirs: + return False + if ascend_ms_dirs and not ascend_pt_dirs: + data_processor = MindsporeDataPreprocessor(ascend_ms_dirs) + elif ascend_pt_dirs and not ascend_ms_dirs: + data_processor = PytorchDataPreprocessor(ascend_pt_dirs) self.cluster_local_data_map[profiling_path] = data_processor.get_data_map() diff --git a/profiler/advisor/analyzer/base_analyzer.py b/profiler/advisor/analyzer/base_analyzer.py index b7fd46df44dd6053068b3a4fb7cb9acf0e602b9e..9a15f89547388302a08a36abfbf7729cc3bd9161 100644 --- a/profiler/advisor/analyzer/base_analyzer.py +++ b/profiler/advisor/analyzer/base_analyzer.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. import logging +import os from functools import wraps from typing import Dict, List, Union from abc import abstractmethod, ABCMeta @@ -25,9 +26,16 @@ from profiler.advisor.result.result import OptimizeResult from profiler.advisor.display.html.render import HTMLRender from profiler.advisor.display.html.priority_background_color import PriorityBackgroundColor from profiler.advisor.utils.utils import safe_division +from profiler.prof_common.file_manager import FileManager logger = logging.getLogger() +ASCEND_PT = "ascend_pt" +ASCEND_MS = "ascend_ms" +PROFILER_INFO_HEAD = "profiler_info_" +PROFILER_INFO_EXTENSION = ".json" +MS_VERSION = "ms_version" + class BaseAnalyzer(VersionControl, metaclass=ABCMeta): _SUPPORT_VERSIONS = EnumParamsParser().get_options(Constant.CANN_VERSION) @@ -38,11 +46,13 @@ class BaseAnalyzer(VersionControl, metaclass=ABCMeta): def __init__(self, collection_path, n_processes: int = 1, **kwargs): self.n_processes = n_processes + self.kwargs = kwargs + self.collection_path = collection_path self.cann_version = kwargs.get(Constant.CANN_VERSION, EnumParamsParser().get_default(Constant.CANN_VERSION)) - self.torch_version = kwargs.get(Constant.TORCH_VERSION, EnumParamsParser().get_default(Constant.TORCH_VERSION)) + self.profiling_type = self.identify_profiling_type( + EnumParamsParser().get_options(Constant.PROFILING_TYPE_UNDER_LINE)) + self.profiling_version = self.identify_profiling_version() self.html_render = HTMLRender() - self.collection_path = collection_path - self.kwargs = kwargs self.dataset_list: Dict[str, List[Dataset]] = {} self.init_dataset_list() self.result = OptimizeResult() @@ -94,6 +104,67 @@ class BaseAnalyzer(VersionControl, metaclass=ABCMeta): def get_priority(self, max_mem_op_dur): pass + def identify_profiling_type(self, profiling_type_list): + profiling_type = None + if self.collection_path.endswith(ASCEND_MS): + profiling_type = [elem for elem in profiling_type_list if Constant.MINDSPORE in elem][0] + elif self.collection_path.endswith(ASCEND_PT): + profiling_type = [elem for elem in profiling_type_list if Constant.PYTORCH in elem][0] + else: + for _, dirs, __ in os.walk(self.collection_path): + is_found_type = False + for dir in dirs: + if dir.endswith(ASCEND_MS): + profiling_type = [elem for elem in profiling_type_list if Constant.MINDSPORE in elem][0] + is_found_type = True + break + elif dir.endswith(ASCEND_PT): + profiling_type = [elem for elem in profiling_type_list if Constant.PYTORCH in elem][0] + is_found_type = True + break + if is_found_type: + break + if self.kwargs.get(Constant.PROFILING_TYPE_UNDER_LINE) and self.kwargs.get( + Constant.PROFILING_TYPE_UNDER_LINE) != profiling_type: + logger.warning("%s The input profiling type %s is inconsistent with the actual profiling type %s.", + self.__class__.__name__, self.kwargs.get(Constant.PROFILING_TYPE_UNDER_LINE), profiling_type) + if not profiling_type: + logger.warning("Unknown profiling type, the default value is set pytorch.") + profiling_type = profiling_type_list[0] + return profiling_type + + def identify_profiling_version(self): + profiling_version = "" + if Constant.MINDSPORE in self.profiling_type: + ascend_dirs = [] + if self.collection_path.endswith(ASCEND_MS): + ascend_dirs.append(self.collection_path) + else: + for root, dirs, _ in os.walk(self.collection_path): + for dir in dirs: + if dir.endswith(ASCEND_MS): + ascend_dirs.append(os.path.join(root, dir)) + if ascend_dirs: + ascend_dir = ascend_dirs[0] + for file_name in os.listdir(ascend_dir): + if file_name.startswith(PROFILER_INFO_HEAD) and file_name.endswith(PROFILER_INFO_EXTENSION): + file_path = os.path.join(ascend_dir, file_name) + config = FileManager.read_json_file(file_path) + profiling_version = config.get(MS_VERSION, "") + break + if profiling_version and self.kwargs.get(Constant.MINDSPORE_VERSION): + if profiling_version != self.kwargs.get(Constant.MINDSPORE_VERSION): + logger.warning("%s The input version %s is inconsistent with the actual version %s.", + self.__class__.__name__, self.kwargs.get(Constant.MINDSPORE_VERSION), + profiling_version) + elif Constant.PYTORCH in self.profiling_type: + profiling_version = self.kwargs.get(Constant.TORCH_VERSION, + EnumParamsParser().get_default(Constant.TORCH_VERSION)) + if self.kwargs.get(Constant.TORCH_VERSION) and profiling_version != self.kwargs.get(Constant.TORCH_VERSION): + logger.warning("%s The input version %s is inconsistent with the actual version %s.", + self.__class__.__name__, self.kwargs.get(Constant.TORCH_VERSION), profiling_version) + return profiling_version + def init_dataset_list(self) -> None: dataset_cls_list = self.dataset_cls_list if len(dataset_cls_list) == 0: diff --git a/profiler/advisor/analyzer/cluster/slow_link_analyzer.py b/profiler/advisor/analyzer/cluster/slow_link_analyzer.py index 10459e719294724e4836d2d2ef531bfef4f561e5..a49ba83774601a7c2b1aba8db2f1aac225cd7774 100644 --- a/profiler/advisor/analyzer/cluster/slow_link_analyzer.py +++ b/profiler/advisor/analyzer/cluster/slow_link_analyzer.py @@ -143,7 +143,8 @@ class SlowLinkAnalyzer(BaseAnalyzer): template_dir="templates", template_name="cluster_analysis.html", cann_version=self.cann_version, - torch_version=self.torch_version, + profiling_type=self.profiling_type, + profiling_version=self.profiling_version, result=result_for_html) def get_global_step_rank(self, bindwidth_type): diff --git a/profiler/advisor/analyzer/cluster/slow_rank_analyzer.py b/profiler/advisor/analyzer/cluster/slow_rank_analyzer.py index 0d73a74eea47af8cca3ada9ddc093c0106cf9356..7b2311157ae7207b4415b6c386854e39e61ba03d 100644 --- a/profiler/advisor/analyzer/cluster/slow_rank_analyzer.py +++ b/profiler/advisor/analyzer/cluster/slow_rank_analyzer.py @@ -134,7 +134,8 @@ class SlowRankAnalyzer(BaseAnalyzer): template_dir="templates", template_name="cluster_analysis.html", cann_version=self.cann_version, - torch_version=self.torch_version, + profiling_type=self.profiling_type, + profiling_version=self.profiling_version, result=result_for_html) def get_global_step_rank(self, dimension): diff --git a/profiler/advisor/analyzer/comparison/comparison_checker.py b/profiler/advisor/analyzer/comparison/comparison_checker.py index dc12f9353bab9696320ca77b9c34788a538708e2..4fa5f082c52562826a4cc0d08d4f3b574604fe97 100644 --- a/profiler/advisor/analyzer/comparison/comparison_checker.py +++ b/profiler/advisor/analyzer/comparison/comparison_checker.py @@ -67,6 +67,9 @@ class ComparisonChecker: if compare_mode is None: return self.compare_mode = compare_mode + if ("Api" in compare_mode) and self.benchmark_profiling_path.endswith("ascend_ms"): + logger.warning("The current compare mode %s does not support Mindspore.", compare_mode) + return compare_interface = ComparisonInterface(self.profiling_path, self.benchmark_profiling_path, self.step, self.benchmark_step) result = compare_interface.compare(self.compare_mode) diff --git a/profiler/advisor/analyzer/computation/profiling_analyzer.py b/profiler/advisor/analyzer/computation/profiling_analyzer.py index 6d525f303cc8c5971bda8a11d16d638ef3dcf2c3..dab4c7d95f4f58ec4c9d139a7f230857930f219a 100644 --- a/profiler/advisor/analyzer/computation/profiling_analyzer.py +++ b/profiler/advisor/analyzer/computation/profiling_analyzer.py @@ -90,6 +90,9 @@ class ProfilingAnalyzer(BaseAnalyzer, ABC): class DynamicShapeAnalyzer(ProfilingAnalyzer): def __init__(self, collection_path, **kwargs) -> None: super().__init__(collection_path, **kwargs) + if collection_path.endswith("ascend_ms"): + logger.warning("Dynamic shape analyzer does not support Mindspore.") + return self.checker = DynamicShapeChecker(self.cann_version) diff --git a/profiler/advisor/analyzer/overall/overall_summary_analyzer.py b/profiler/advisor/analyzer/overall/overall_summary_analyzer.py index 3df71fe8149dec81d40030d1520863be1d2723f8..143eb854be2f90e9b0325ace537cc3961b54d747 100644 --- a/profiler/advisor/analyzer/overall/overall_summary_analyzer.py +++ b/profiler/advisor/analyzer/overall/overall_summary_analyzer.py @@ -230,7 +230,8 @@ class OverallSummaryAnalyzer(BaseAnalyzer): template_dir="templates", template_name="cluster_analysis.html", cann_version=self.cann_version, - torch_version=self.torch_version, + profiling_type=self.profiling_type, + profiling_version=self.profiling_version, result=result_for_html) def get_priority(self): diff --git a/profiler/advisor/analyzer/schedule/dispatch/timeline_op_dispatch_analyzer.py b/profiler/advisor/analyzer/schedule/dispatch/timeline_op_dispatch_analyzer.py index ed0500d3b23440151d60b8186e7e12aba007ab89..4f84d93a5699ba8eff33bdbce35ed9666241cd7d 100644 --- a/profiler/advisor/analyzer/schedule/dispatch/timeline_op_dispatch_analyzer.py +++ b/profiler/advisor/analyzer/schedule/dispatch/timeline_op_dispatch_analyzer.py @@ -49,6 +49,9 @@ class OpDispatchAnalyzer(BaseAnalyzer): :param data: input datasets :return: result """ + if "mindspore" in self.profiling_type: + logger.warning("The analyzer %s does not support MindSpore.", self.__class__.__name__) + return self.result self.get_op_compile_info(self.dataset) self.make_record(self.result) self.make_render(self.html_render, rank=kwargs.get('rank')) diff --git a/profiler/advisor/analyzer/schedule/fusion_ops/fusion_ops_analyzer.py b/profiler/advisor/analyzer/schedule/fusion_ops/fusion_ops_analyzer.py index 80ac80061557242f71bb939ba2f17c5ca68e6862..098fab15316a9bf541c0e68e8d3838d52723d5a7 100644 --- a/profiler/advisor/analyzer/schedule/fusion_ops/fusion_ops_analyzer.py +++ b/profiler/advisor/analyzer/schedule/fusion_ops/fusion_ops_analyzer.py @@ -56,7 +56,9 @@ class TimelineFusionOpsAnalyzer(BaseAnalyzer): for mode in [Constant.ATEN.lower(), Constant.OPTIMIZER.lower()]: - for op_combined, npu_apis in tqdm(getattr(init_timeline_ops_db(self.cann_version, self.torch_version), + for op_combined, npu_apis in tqdm(getattr(init_timeline_ops_db(self.cann_version, + self.profiling_type, + self.profiling_version), f"_{mode}_op_api_map").items(), leave=False, ncols=100, desc="Scanning timeline for affinity apis"): for npu_api in npu_apis.split("/"): @@ -94,7 +96,7 @@ class TimelineFusionOpsAnalyzer(BaseAnalyzer): return desc = f"Found {len(format_timeline_result(self.matched_op_stacks))} apis to be replaced" \ - f" based on the runtime env cann-{self.cann_version} and torch-{self.torch_version}" + f" based on the runtime env cann-{self.cann_version} and torch-{self.profiling_version}" suggestion = "Please replace training api according to sub table 'Affinity training api'" if self.empty_stacks: desc += ", but with no stack" @@ -131,7 +133,8 @@ class TimelineFusionOpsAnalyzer(BaseAnalyzer): template_dir="templates", template_name="affinity_api.html", cann_version=self.cann_version, - torch_version=self.torch_version, + profiling_type=self.profiling_type, + profiling_version=self.profiling_version, empty_stacks=self.empty_stacks, with_stack_doc_url=Config().timeline_with_stack_doc_url, api_doc_url=Config().timeline_api_doc_url, diff --git a/profiler/advisor/analyzer/schedule/gc/gc_analyzer.py b/profiler/advisor/analyzer/schedule/gc/gc_analyzer.py index b59a8fc2e2a25428e34cb51917462f9f6162bc46..8c77e93b333322fd04cd239caa4d8c49a20b7cc6 100644 --- a/profiler/advisor/analyzer/schedule/gc/gc_analyzer.py +++ b/profiler/advisor/analyzer/schedule/gc/gc_analyzer.py @@ -36,6 +36,9 @@ class GcAnalyzer(BaseAnalyzer): @BaseAnalyzer.check_data((ScheduleAnalysisDataset.get_key(),)) def optimize(self, **kwargs): + if "mindspore" in self.profiling_type: + logger.warning("The analyzer %s does not support MindSpore.", self.__class__.__name__) + return self.result gc_checker = GcChecker() gc_checker.check_gc(self.timeline_event_dataset, rank=kwargs.get("rank"), stage=kwargs.get("stage")) gc_checker.make_record(self.result) diff --git a/profiler/advisor/common/timeline/fusion_ops_db.py b/profiler/advisor/common/timeline/fusion_ops_db.py index 171786b15c5637c899f01b1a7c2fe4c16de61e79..11727bf3ed299777a3dab3457c396bff3b75365e 100644 --- a/profiler/advisor/common/timeline/fusion_ops_db.py +++ b/profiler/advisor/common/timeline/fusion_ops_db.py @@ -29,10 +29,12 @@ logger = logging.getLogger() logger.setLevel(get_log_level()) -def init_timeline_ops_db(cann_version=None, torch_version=None): +def init_timeline_ops_db(cann_version=None, profiling_type=None, profiling_version=None): logger.debug("init operators database") - return FusionOperatorDB(cann_version=cann_version, torch_version=torch_version) + return FusionOperatorDB(cann_version=cann_version, + profiling_type=profiling_type, + profiling_version=profiling_version) def get_timeline_fusion_ops_yaml_path(): @@ -65,17 +67,18 @@ def get_timeline_fusion_ops_yaml_path(): class FusionOperatorDB: - def __init__(self, file_path=None, cann_version=None, torch_version=None): + def __init__(self, cann_version=None, profiling_type=None, profiling_version=None): self.timeline_fusion_ops_yaml_path = os.path.normpath(get_timeline_fusion_ops_yaml_path()) - self.cann_version = cann_version or EnumParamsParser().get_default(Constant.CANN_VERSION) - self.torch_version = torch_version or EnumParamsParser().get_default(Constant.TORCH_VERSION) + self.profiling_type = profiling_type or EnumParamsParser().get_default(Constant.PROFILING_TYPE_UNDER_LINE) + self.profiling_version = profiling_version or EnumParamsParser().get_default(Constant.PROFILING_TYPE_UNDER_LINE) self._supported_version_dict = {} self.is_empty = False self.timeline_op_rule_handler = TimelineOpRuleHandler() - self.fusion_operator = self._load_yaml(self.timeline_fusion_ops_yaml_path) + self.fusion_operator = self._load_yaml( + self.timeline_fusion_ops_yaml_path) if profiling_type == Constant.PYTORCH else {} self._dequeue_op_names = [] self._aten_op_names = [] @@ -126,7 +129,7 @@ class FusionOperatorDB: def regenerate_timeline_op_rule_with_version(self, cann_version=None, torch_version=None): cann_version = cann_version or self.cann_version - torch_version = torch_version or self.torch_version + torch_version = torch_version or self.profiling_version unique_id = self._get_unique_id_in_supported_version_dict(cann_version=cann_version, torch_version=torch_version) self.regenerate_timeline_op_rule_with_unique_id(unique_id) @@ -180,7 +183,7 @@ class FusionOperatorDB: if not is_version_supported: # 若规则库不支持当前版本, 则log警告信息 logger.warning("Unsupported versions: cann-%s and torch-%s, supported version list of ['cann', 'torch'] " - "is %s", self.cann_version, self.torch_version, self._supported_version_dict.values()) + "is %s", self.cann_version, self.profiling_version, self._supported_version_dict.values()) return is_version_supported def _is_version_supported_in_supported_version_dict(self, cann_version=None, torch_version=None): @@ -208,7 +211,7 @@ class FusionOperatorDB: torch_version_list = [torch_version_list] cann_version = cann_version or self.cann_version - torch_version = torch_version or self.torch_version + torch_version = torch_version or self.profiling_version if (cann_version in cann_version_list) and (torch_version in torch_version_list): return True diff --git a/profiler/advisor/config/enum_parameters.yaml b/profiler/advisor/config/enum_parameters.yaml index b1a0548d480b8722609df40ae8e9331b5d3d34bd..678fe72b43c7f5b2fd66b3f38c3114cc9793cd50 100644 --- a/profiler/advisor/config/enum_parameters.yaml +++ b/profiler/advisor/config/enum_parameters.yaml @@ -6,7 +6,9 @@ arguments: - 7.0.RC1 - 7.0.0 - 8.0.RC1 - default: 8.0.RC1 + - 8.0.RC2 + - 8.0.0 + default: 8.0.0 torch_version: type: str @@ -14,7 +16,12 @@ arguments: - 1.11.0 - 2.1.0 default: 2.1.0 - + mindspore_version: + type: str + options: + - 2.3.0 + - 2.4.0 + default: 2.4.0 analysis_dimensions: type: list options: @@ -28,10 +35,11 @@ arguments: profiling_type: type: str options: - - ascend_pytorch_profiler + - pytorch - mslite - msprof - default: ascend_pytorch_profiler + - mindspore + default: pytorch envs: ADVISOR_ANALYZE_PROCESSES: diff --git a/profiler/advisor/config/profiling_data_version_config.yaml b/profiler/advisor/config/profiling_data_version_config.yaml index ed064e287583b699379b5707a21be301164c2b74..1c82a8a6bcfbd7ae3d09cab4ca1852b875b2e64c 100644 --- a/profiler/advisor/config/profiling_data_version_config.yaml +++ b/profiler/advisor/config/profiling_data_version_config.yaml @@ -1,4 +1,28 @@ versions: + - version: 8.0.0 + dirs_pattern: + ASCEND_PROFILER_OUTPUT: [ op_summary, msprof ] + ^PROF_\d{6}_\d{17}_\w+$: + mindstudio_profiler_output: [ op_summary, msprof ] + class_attr: + op_summary: OpSummary + msprof: Msprof + file_attr: + msprof: [trace_view.json, '^msprof_\d{14}\.json$'] + op_summary: [ kernel_details.csv, '^op_summary_\d{14}\.csv$' ] + + - version: 8.0.RC2 + dirs_pattern: + ASCEND_PROFILER_OUTPUT: [ op_summary, msprof ] + ^PROF_\d{6}_\d{17}_\w+$: + mindstudio_profiler_output: [ op_summary, msprof ] + class_attr: + op_summary: OpSummary + msprof: Msprof + file_attr: + msprof: [trace_view.json, '^msprof_\d{14}\.json$'] + op_summary: [ kernel_details.csv, '^op_summary_\d{14}\.csv$' ] + - version: 8.0.RC1 dirs_pattern: ASCEND_PROFILER_OUTPUT: [ op_summary, msprof ] diff --git a/profiler/advisor/dataset/communication/communication_dataset.py b/profiler/advisor/dataset/communication/communication_dataset.py index 6a346f52ada4d53ac630d2aeecff6304a2a69b87..d11e18c3e575afe7bac0e4eeb795e615ecfe37b5 100644 --- a/profiler/advisor/dataset/communication/communication_dataset.py +++ b/profiler/advisor/dataset/communication/communication_dataset.py @@ -30,7 +30,7 @@ class CommunicationDataset: def __init__(self, collection_path, data: dict, **kwargs) -> None: self.timeline_dir = collection_path - if not self.timeline_dir.endswith("ascend_pt"): + if not self.timeline_dir.endswith("ascend_pt") and not self.timeline_dir.endswith("ascend_ms"): return self.timeline_data_list = self.get_file_path_from_directory( self.timeline_dir, diff --git a/profiler/advisor/display/html/templates/affinity_api.html b/profiler/advisor/display/html/templates/affinity_api.html index 7cd3d7ad33d0220c7aba055721eddf049161a0d8..b227afae9624cadb5ce753c80f1e8719040eacb4 100644 --- a/profiler/advisor/display/html/templates/affinity_api.html +++ b/profiler/advisor/display/html/templates/affinity_api.html @@ -8,14 +8,14 @@ The analysis results of following affinity APIs are based on runtime env cann-{{ cann_version }} and - torch-{{ torch_version }} + {{profiling_type}}-{{ profiling_type }}
{% if empty_stacks %} Suggestion: These APIs have no code stack. If parameter 'with_stack=False' was set while profiling, please refer to - Ascend PyTorch Profiler to set + Ascend Profiler to set 'with_stack=True'. Otherwise, ignore following affinity APIs due to backward broadcast lack of stack. {% endif %} diff --git a/profiler/advisor/rules/timeline_fusion_ops.yaml b/profiler/advisor/rules/timeline_fusion_ops.yaml index 46e02fef77785a3bf3da65899539c42ac05fadd4..3337c938625ccd4b4ea77a0dafa9879222cf1bfe 100644 --- a/profiler/advisor/rules/timeline_fusion_ops.yaml +++ b/profiler/advisor/rules/timeline_fusion_ops.yaml @@ -45,6 +45,18 @@ "(slice|chunk)-mul-mul-sigmoid" ] - cann_version: 8.0.RC1 + torch_version: [1.11.0, 2.1.0] + unique_id: 3 + inherit_unique_id: 2 + operator_rules: + aten: + add: + torch_npu.npu_geglu: [ "(slice|chunk)-gelu-mul", "(slice|chunk)-mul-gelu" ] + torch_npu.npu_group_norm_silu: [ "group_norm-silu" ] + torch.addmm: [ "mul-mul-add" ] + torch_npu.npu_add_layer_norm: [ "add-layer_norm" ] + +- cann_version: 8.0.0 torch_version: [1.11.0, 2.1.0] unique_id: 3 inherit_unique_id: 2 diff --git a/profiler/cli/analyze_cli.py b/profiler/cli/analyze_cli.py index c91c55c337a332bf631f62624f27da17a5e0e96c..7c93d224cdec1c8c574d152639ab4ed948c7a04b 100644 --- a/profiler/cli/analyze_cli.py +++ b/profiler/cli/analyze_cli.py @@ -37,17 +37,12 @@ def analyze_cli(**kwargs): default=EnumParamsParser().get_default(Constant.CANN_VERSION), help='The CANN software version, which can be viewed by executing the following command: ' '"cat /usr/local/Ascend/ascend-toolkit/latest/aarch64-linux/ascend_toolkit_install.info"') -@click.option('--torch_version', '-tv', 'torch_version', - type=click.Choice(EnumParamsParser().get_options(Constant.TORCH_VERSION), case_sensitive=False), - default=EnumParamsParser().get_default(Constant.TORCH_VERSION), - help='The runtime torch version, which can be detected by exec command "pip show torch"') @click.option("-pt", "--profiling_type", metavar="", - default=EnumParamsParser().get_default(Constant.PROFILING_TYPE_UNDER_LINE), required=False, type=click.Choice(EnumParamsParser().get_options(Constant.PROFILING_TYPE_UNDER_LINE)), - help="enter the profiling type, selectable range ascend_pytorch_profiler, mslite ,msprof") + help="enter the profiling type, selectable range pytorch, mindspore, mslite ,msprof") @click.option("--force", is_flag=True, help="Indicates whether to skip file size verification and owner verification") diff --git a/profiler/cluster_analyse/prof_bean/step_trace_time_bean.py b/profiler/cluster_analyse/prof_bean/step_trace_time_bean.py index b0a3be4f5eaccea70aa912bc85e68d70dbda3bde..3cf4bc4fa5b1a8c8ccf93c010fe5fe8e9843e513 100644 --- a/profiler/cluster_analyse/prof_bean/step_trace_time_bean.py +++ b/profiler/cluster_analyse/prof_bean/step_trace_time_bean.py @@ -14,6 +14,10 @@ # limitations under the License. +import logging + +logger = logging.getLogger() + class StepTraceTimeBean: STEP = "Step" COMPLEMENT_HEADER = ["Step", "Type", "Index"] @@ -27,7 +31,11 @@ class StepTraceTimeBean: for field_name in self._data.keys(): if field_name == self.STEP: continue - row.append(float(self._data.get(field_name, ))) + try: + row.append(float(self._data.get(field_name, ))) + except Exception as e: + logger.warning(e) + row.append(0) return row @property diff --git a/profiler/prof_common/constant.py b/profiler/prof_common/constant.py index 86c86a8fe527425d30a37e296f778ed6f4d087f6..78cf1070ffd8ab1233065c6a7e25a3df9e46f33d 100644 --- a/profiler/prof_common/constant.py +++ b/profiler/prof_common/constant.py @@ -379,4 +379,8 @@ class Constant(object): DISABLE_PROFILING_COMPARISON = "DISABLE_PROFILING_COMPARISON" FREE_DURATION_FOR_GC_ANALYSIS = "FREE_DURATION_FOR_GC_ANALYSIS" - DISABLE_AFFINITY_API = "DISABLE_AFFINITY_API" \ No newline at end of file + DISABLE_AFFINITY_API = "DISABLE_AFFINITY_API" + + MINDSPORE_VERSION = "mindspore_version" + PYTORCH = "pytorch" + MINDSPORE = "mindspore" \ No newline at end of file diff --git a/profiler/test/st/advisor/test_advisor_cmd_single_ascend_pt_no_compare.py b/profiler/test/st/advisor/test_advisor_cmd_single_ascend_pt_no_compare.py index ce6eeb3a39c6944037abeeb835bdad53f8e7efbd..dfb7250480592430770ac63ac3be4a1aec072c51 100644 --- a/profiler/test/st/advisor/test_advisor_cmd_single_ascend_pt_no_compare.py +++ b/profiler/test/st/advisor/test_advisor_cmd_single_ascend_pt_no_compare.py @@ -16,7 +16,7 @@ class TestAdvisorCmdSingleAscendPtNoCompare(TestCase): "/home/dcs-50/smoke_project_for_msprof_analyze/mstt_profiler/st_data") BASE_PROFILING_PATH = os.path.join(ST_DATA_PATH, "cluster_data_3", "n122-122-067_12380_20240912033946038_ascend_pt") OUTPUT_PATH = os.path.join(os.path.abspath(os.path.dirname(__file__)), "TestAdvisorCmdSingleAscendPtNoCompare") - ALL_OUTPUT_PATH = os.path.join(OUTPUT_PATH,"all") + ALL_OUTPUT_PATH = os.path.join(OUTPUT_PATH, "all") COMPUTATION_OUTPUT_PATH = os.path.join(OUTPUT_PATH, "computation") SCHEDULE_OUTPUT_PATH = os.path.join(OUTPUT_PATH, "schedule") RESULT_EXCEL = {} @@ -27,22 +27,21 @@ class TestAdvisorCmdSingleAscendPtNoCompare(TestCase): PathManager.make_dir_safety(self.ALL_OUTPUT_PATH) PathManager.make_dir_safety(self.COMPUTATION_OUTPUT_PATH) PathManager.make_dir_safety(self.SCHEDULE_OUTPUT_PATH) - cmd_all = ["msprof-analyze", "advisor", "all" ,"-d", self.BASE_PROFILING_PATH, "-o",self.ALL_OUTPUT_PATH] + cmd_all = ["msprof-analyze", "advisor", "all", "-d", self.BASE_PROFILING_PATH, "-o", self.ALL_OUTPUT_PATH] if execute_cmd(cmd_all) != self.COMMAND_SUCCESS or not os.path.exists(self.ALL_OUTPUT_PATH): self.assertTrue(False, msg="advisor [all] task failed.") - cmd_computation = ["msprof-analyze", "advisor", "computation" ,"-d", self.BASE_PROFILING_PATH, "-o", - self.COMPUTATION_OUTPUT_PATH] - completed_process_computation = subprocess.run(cmd_computation, capture_output=True, shell=False) - if completed_process_computation.returncode != self.COMMAND_SUCCESS or not os.path.exists(self.COMPUTATION_OUTPUT_PATH): + + cmd_computation = ["msprof-analyze", "advisor", "computation", "-d", self.BASE_PROFILING_PATH, "-o", + self.COMPUTATION_OUTPUT_PATH] + if execute_cmd(cmd_computation) != self.COMMAND_SUCCESS or not os.path.exists(self.COMPUTATION_OUTPUT_PATH): self.assertTrue(False, msg="advisor [computation] task failed.") - cmd_schedule = ["msprof-analyze", "advisor", "schedule" ,"-d", self.BASE_PROFILING_PATH, "-o", - self.SCHEDULE_OUTPUT_PATH] - completed_process_schedule = subprocess.run(cmd_schedule, capture_output=True, shell=False) - if completed_process_schedule.returncode != self.COMMAND_SUCCESS or not os.path.exists( - self.SCHEDULE_OUTPUT_PATH): + + cmd_schedule = ["msprof-analyze", "advisor", "schedule", "-d", self.BASE_PROFILING_PATH, "-o", + self.SCHEDULE_OUTPUT_PATH] + if execute_cmd(cmd_schedule) != self.COMMAND_SUCCESS or not os.path.exists(self.SCHEDULE_OUTPUT_PATH): self.assertTrue(False, msg="advisor [schedule] task failed.") - self.RESULT_HTML,self.RESULT_EXCEL = get_files(self.OUTPUT_PATH) + self.RESULT_HTML, self.RESULT_EXCEL = get_files(self.OUTPUT_PATH) def teardown_class(self): PathManager.remove_path_safety(self.OUTPUT_PATH) @@ -58,32 +57,32 @@ class TestAdvisorCmdSingleAscendPtNoCompare(TestCase): "Operator dispatch" ] - #True presents the attr is nan - description_len = [6,1,3,2,1,1,1] - suggestion_len = [True,1,1,2,5,1,1] - problem_count = [True,True,True,2.0,1.0,True,True] - total_time = [True,True,True,57674709.54,True,True,True] - time_ratio = [True,True,True,0.0,True,True,True] - income = [True,True,True,True,True,True,True] - income_ratio = [True,True,True,True,True,True,True] + # True presents the attr is nan + description_len = [6, 1, 3, 2, 1, 1, 1] + suggestion_len = [True, 1, 1, 2, 5, 1, 1] + problem_count = [True, True, True, 2.0, 1.0, True, True] + total_time = [True, True, True, 57674709.54, True, True, True] + time_ratio = [True, True, True, 0.0, True, True, True] + income = [True, True, True, True, True, True, True] + income_ratio = [True, True, True, True, True, True, True] try: - df = pd.read_excel(self.RESULT_EXCEL.get("all",None), sheet_name='problems',header=0) + df = pd.read_excel(self.RESULT_EXCEL.get("all", None), sheet_name='problems', header=0) except FileNotFoundError: - logging.error("File %s not found.", self.RESULT_EXCEL.get("all",None)) + logging.error("File %s not found.", self.RESULT_EXCEL.get("all", None)) return for index, row in df.iterrows(): self.assertEqual(category[index], row["category"]) self.assertEqual(description_len[index], len(row["description"].split("\n"))) - self.assertEqual(suggestion_len[index], isinstance(row["suggestion"],float) or - len(row["suggestion"].split("\n"))) + self.assertEqual(suggestion_len[index], isinstance(row["suggestion"], float) or + len(row["suggestion"].split("\n"))) self.assertEqual(problem_count[index], (math.isnan(row["problem count"]) or row["problem count"])) self.assertEqual(total_time[index], (math.isnan(row["total_time(us)"]) or - round(row["total_time(us)"],2))) - self.assertEqual(time_ratio[index], (math.isnan(row["time ratio"]) or round(row["time ratio"],2))) - self.assertEqual(income[index], (math.isnan(row["income(us)"]) or round(row["income(us)"],2))) + round(row["total_time(us)"], 2))) + self.assertEqual(time_ratio[index], (math.isnan(row["time ratio"]) or round(row["time ratio"], 2))) + self.assertEqual(income[index], (math.isnan(row["income(us)"]) or round(row["income(us)"], 2))) self.assertEqual(income_ratio[index], (math.isnan(row["income ratio"]) or - round(row["income ratio"],2))) + round(row["income ratio"], 2))) def test_computation_problems(self): category = [ @@ -92,7 +91,7 @@ class TestAdvisorCmdSingleAscendPtNoCompare(TestCase): "Dynamic shape operator", ] - #True presents the attr is nan + # True presents the attr is nan description_len = [6, 2, 1] suggestion_len = [True, 2, 5] problem_count = [True, 2.0, 1.0] @@ -101,15 +100,15 @@ class TestAdvisorCmdSingleAscendPtNoCompare(TestCase): income = [True, True, True] income_ratio = [True, True, True] try: - df = pd.read_excel(self.RESULT_EXCEL.get("computation",None), sheet_name='problems', header=0) + df = pd.read_excel(self.RESULT_EXCEL.get("computation", None), sheet_name='problems', header=0) except FileNotFoundError: - logging.error("File %s not found.", self.RESULT_EXCEL.get("computation",None)) + logging.error("File %s not found.", self.RESULT_EXCEL.get("computation", None)) return for index, row in df.iterrows(): self.assertEqual(category[index], row["category"]) self.assertEqual(description_len[index], len(row["description"].split("\n"))) - self.assertEqual(suggestion_len[index], (isinstance(row["suggestion"],float) or + self.assertEqual(suggestion_len[index], (isinstance(row["suggestion"], float) or len(row["suggestion"].split("\n")))) self.assertEqual(problem_count[index], (math.isnan(row["problem count"]) or row["problem count"])) self.assertEqual(total_time[index], (math.isnan(row["total_time(us)"]) or @@ -126,7 +125,7 @@ class TestAdvisorCmdSingleAscendPtNoCompare(TestCase): "Operator dispatch" ] - #True presents the attr is nan + # True presents the attr is nan description_len = [6, 1, 1] suggestion_len = [True, 1, 1] problem_count = [True, True, True] @@ -135,15 +134,15 @@ class TestAdvisorCmdSingleAscendPtNoCompare(TestCase): income = [True, True, True] income_ratio = [True, True, True] try: - df = pd.read_excel(self.RESULT_EXCEL.get("schedule",None), sheet_name='problems', header=0) + df = pd.read_excel(self.RESULT_EXCEL.get("schedule", None), sheet_name='problems', header=0) except FileNotFoundError: - logging.error("File %s not found.", self.RESULT_EXCEL.get("schedule",None)) + logging.error("File %s not found.", self.RESULT_EXCEL.get("schedule", None)) return for index, row in df.iterrows(): self.assertEqual(category[index], row["category"]) self.assertEqual(description_len[index], len(row["description"].split("\n"))) - self.assertEqual(suggestion_len[index], (isinstance(row["suggestion"] ,float) or + self.assertEqual(suggestion_len[index], (isinstance(row["suggestion"], float) or len(row["suggestion"].split("\n")))) self.assertEqual(problem_count[index], (math.isnan(row["problem count"]) or row["problem count"])) self.assertEqual(total_time[index], (math.isnan(row["total_time(us)"]) or @@ -152,6 +151,7 @@ class TestAdvisorCmdSingleAscendPtNoCompare(TestCase): self.assertEqual(income[index], (math.isnan(row["income(us)"]) or round(row["income(us)"], 2))) self.assertEqual(income_ratio[index], (math.isnan(row["income ratio"]) or round(row["income ratio"], 2))) + def test_overall_summary(self): performance_index = [ "Computing Time", " -- Flash Attention", @@ -170,9 +170,9 @@ class TestAdvisorCmdSingleAscendPtNoCompare(TestCase): test_pattern = ["all", "computation", "schedule"] for pattern in test_pattern: try: - df = pd.read_excel(self.RESULT_EXCEL.get(pattern,None), sheet_name='overall summary', header=0) + df = pd.read_excel(self.RESULT_EXCEL.get(pattern, None), sheet_name='overall summary', header=0) except FileNotFoundError: - logging.error("File %s not found.", self.RESULT_EXCEL.get(pattern,None)) + logging.error("File %s not found.", self.RESULT_EXCEL.get(pattern, None)) return for index, row in df.iterrows(): @@ -180,7 +180,7 @@ class TestAdvisorCmdSingleAscendPtNoCompare(TestCase): self.assertEqual(duration[index], row["Duration(ms)"]) self.assertEqual(duration_ratio[index], row["Duration Ratio"]) - soup = BeautifulSoup(open(self.RESULT_HTML.get(pattern,None)), 'html.parser') + soup = BeautifulSoup(open(self.RESULT_HTML.get(pattern, None)), 'html.parser') for h2 in soup.find_all('h2'): if h2.contents[0] == "overall summary": div_content = h2.next.next.next @@ -194,52 +194,58 @@ class TestAdvisorCmdSingleAscendPtNoCompare(TestCase): def test_all_bandwidth_contention_analysis(self): bandwidth_contention_analysis = [ - "hcom_allGather__508_1_1","hcom_allGather__508_4_1","hcom_allGather__508_8_1", - "hcom_allGather__508_108_1","hcom_allGather__508_112_1","hcom_allGather__508_113_1", - "hcom_allGather__508_137_1","hcom_allGather__508_141_1","hcom_allGather__508_145_1", - "hcom_allGather__508_153_1","hcom_allGather__508_157_1","hcom_allGather__508_173_1", - "hcom_allGather__508_177_1","hcom_allGather__508_181_1","hcom_allGather__508_209_1", - "hcom_reduceScatter__868_261_1","hcom_reduceScatter__868_266_1","hcom_allGather__508_276_1", - "hcom_reduceScatter__508_283_1","hcom_reduceScatter__508_291_1","hcom_reduceScatter__508_299_1", - "hcom_reduceScatter__508_307_1","hcom_allGather__508_308_1","hcom_reduceScatter__508_315_1", - "hcom_reduceScatter__508_323_1","hcom_reduceScatter__508_331_1","hcom_reduceScatter__508_339_1", - "hcom_reduceScatter__508_347_1","hcom_reduceScatter__508_355_1","hcom_allGather__508_356_1", - "hcom_reduceScatter__508_363_1","hcom_reduceScatter__508_371_1","hcom_allGather__508_372_1", - "hcom_reduceScatter__508_379_1","hcom_reduceScatter__508_387_1","hcom_allGather__508_388_1", - "hcom_reduceScatter__508_395_1","hcom_reduceScatter__508_403_1","hcom_allGather__508_404_1", - "hcom_reduceScatter__508_411_1","hcom_reduceScatter__508_419_1","hcom_reduceScatter__508_427_1", - "hcom_reduceScatter__508_435_1","hcom_reduceScatter__508_443_1","hcom_reduceScatter__508_451_1", - "hcom_reduceScatter__508_459_1","hcom_reduceScatter__508_467_1","hcom_allGather__508_468_1", - "hcom_reduceScatter__508_475_1","hcom_reduceScatter__508_483_1","hcom_reduceScatter__508_491_1", - "hcom_reduceScatter__508_499_1","hcom_reduceScatter__508_507_1","hcom_reduceScatter__508_515_1", - "hcom_allGather__508_516_1","hcom_reduceScatter__508_523_1","hcom_reduceScatter__508_531_1", - "hcom_reduceScatter__508_539_1","hcom_reduceScatter__508_547_1","hcom_reduceScatter__508_555_1", - "hcom_reduceScatter__508_563_1","hcom_reduceScatter__508_571_1","hcom_reduceScatter__508_579_1", - "hcom_reduceScatter__508_587_1","hcom_allGather__508_588_1","hcom_reduceScatter__508_595_1", - "hcom_reduceScatter__508_603_1","hcom_reduceScatter__508_611_1","hcom_reduceScatter__508_619_1", - "hcom_reduceScatter__508_627_1","hcom_reduceScatter__508_635_1","hcom_reduceScatter__508_643_1", - "hcom_allGather__508_644_1","hcom_reduceScatter__508_651_1","hcom_reduceScatter__508_659_1", - "hcom_reduceScatter__508_667_1","hcom_reduceScatter__508_675_1","hcom_reduceScatter__508_683_1" + "hcom_allGather__508_1_1", "hcom_allGather__508_4_1", "hcom_allGather__508_8_1", + "hcom_allGather__508_108_1", "hcom_allGather__508_112_1", "hcom_allGather__508_113_1", + "hcom_allGather__508_137_1", "hcom_allGather__508_141_1", "hcom_allGather__508_145_1", + "hcom_allGather__508_153_1", "hcom_allGather__508_157_1", "hcom_allGather__508_173_1", + "hcom_allGather__508_177_1", "hcom_allGather__508_181_1", "hcom_allGather__508_209_1", + "hcom_reduceScatter__868_261_1", "hcom_reduceScatter__868_266_1", "hcom_allGather__508_276_1", + "hcom_reduceScatter__508_283_1", "hcom_reduceScatter__508_291_1", "hcom_reduceScatter__508_299_1", + "hcom_reduceScatter__508_307_1", "hcom_allGather__508_308_1", "hcom_reduceScatter__508_315_1", + "hcom_reduceScatter__508_323_1", "hcom_reduceScatter__508_331_1", "hcom_reduceScatter__508_339_1", + "hcom_reduceScatter__508_347_1", "hcom_reduceScatter__508_355_1", "hcom_allGather__508_356_1", + "hcom_reduceScatter__508_363_1", "hcom_reduceScatter__508_371_1", "hcom_allGather__508_372_1", + "hcom_reduceScatter__508_379_1", "hcom_reduceScatter__508_387_1", "hcom_allGather__508_388_1", + "hcom_reduceScatter__508_395_1", "hcom_reduceScatter__508_403_1", "hcom_allGather__508_404_1", + "hcom_reduceScatter__508_411_1", "hcom_reduceScatter__508_419_1", "hcom_reduceScatter__508_427_1", + "hcom_reduceScatter__508_435_1", "hcom_reduceScatter__508_443_1", "hcom_reduceScatter__508_451_1", + "hcom_reduceScatter__508_459_1", "hcom_reduceScatter__508_467_1", "hcom_allGather__508_468_1", + "hcom_reduceScatter__508_475_1", "hcom_reduceScatter__508_483_1", "hcom_reduceScatter__508_491_1", + "hcom_reduceScatter__508_499_1", "hcom_reduceScatter__508_507_1", "hcom_reduceScatter__508_515_1", + "hcom_allGather__508_516_1", "hcom_reduceScatter__508_523_1", "hcom_reduceScatter__508_531_1", + "hcom_reduceScatter__508_539_1", "hcom_reduceScatter__508_547_1", "hcom_reduceScatter__508_555_1", + "hcom_reduceScatter__508_563_1", "hcom_reduceScatter__508_571_1", "hcom_reduceScatter__508_579_1", + "hcom_reduceScatter__508_587_1", "hcom_allGather__508_588_1", "hcom_reduceScatter__508_595_1", + "hcom_reduceScatter__508_603_1", "hcom_reduceScatter__508_611_1", "hcom_reduceScatter__508_619_1", + "hcom_reduceScatter__508_627_1", "hcom_reduceScatter__508_635_1", "hcom_reduceScatter__508_643_1", + "hcom_allGather__508_644_1", "hcom_reduceScatter__508_651_1", "hcom_reduceScatter__508_659_1", + "hcom_reduceScatter__508_667_1", "hcom_reduceScatter__508_675_1", "hcom_reduceScatter__508_683_1" ] duration = [ - 8.3454,13.8113,39.8263,21.6036,38.2598,5.3913,13.4007,9.6871,8.8002,10.0535,8.3423,9.3205,11.3891, - 9.473,12.7247,19.4176,13.2621,16.3541,127.5414,127.288,126.6839,129.0707,11.8205,128.8378,130.0548, - 128.3927,124.9711,128.0221,122.8157,11.7839,127.0278,123.3328,11.9078,122.3141,123.1837,11.2561, - 123.8337,127.5955,11.5881,123.0412,128.4852,122.3674,127.1958,127.5779,129.6155,127.2981,125.5495, - 11.0916,127.4827,126.4632,125.0414,123.9187,125.168,127.1,12.6763,126.3728,126.9693,127.677, - 127.1439,127.2013,127.9102,125.7989,126.4961,127.6573,12.2088,127.6283,126.3803,129.8238,126.2997, - 127.4806,129.2007,127.2733,12.0963,126.8322,127.5317,126.482,127.8283,129.2951 + 8.3454, 13.8113, 39.8263, 21.6036, 38.2598, 5.3913, 13.4007, 9.6871, 8.8002, 10.0535, 8.3423, 9.3205, + 11.3891, + 9.473, 12.7247, 19.4176, 13.2621, 16.3541, 127.5414, 127.288, 126.6839, 129.0707, 11.8205, 128.8378, + 130.0548, + 128.3927, 124.9711, 128.0221, 122.8157, 11.7839, 127.0278, 123.3328, 11.9078, 122.3141, 123.1837, 11.2561, + 123.8337, 127.5955, 11.5881, 123.0412, 128.4852, 122.3674, 127.1958, 127.5779, 129.6155, 127.2981, 125.5495, + 11.0916, 127.4827, 126.4632, 125.0414, 123.9187, 125.168, 127.1, 12.6763, 126.3728, 126.9693, 127.677, + 127.1439, 127.2013, 127.9102, 125.7989, 126.4961, 127.6573, 12.2088, 127.6283, 126.3803, 129.8238, 126.2997, + 127.4806, 129.2007, 127.2733, 12.0963, 126.8322, 127.5317, 126.482, 127.8283, 129.2951 ] bandwidth = [ - 5.49,4.8,5.99,14.13,3.24,6.25,8.52,5.17,5.34,8.24,5.43,6.15,9.79,5.55,4.39,13.35,13.14,3.61,2.51, - 2.88,2.83,3.07,4.81,2.55,2.57,2.73,2.84,2.44,3.01,4.95,2.63,3.06,3.77,2.88,3.44,4.72,2.91,3.21, - 4.47,2.38,2.31,2.9,4.26,3.57,2.31,2.24,2.81,4.37,2.67,2.8,2.74,2.16,2.79,2.88,5.79,2.75,2.93,2.88, - 2.31,2.72,2.39,2.6,2.55,2.58,4.29,2.69,2.86,2.09,3.12,2.31,2.28,2.87,6.97,3.1,2.35,3.4,2.61,2.62 + 5.49, 4.8, 5.99, 14.13, 3.24, 6.25, 8.52, 5.17, 5.34, 8.24, 5.43, 6.15, 9.79, 5.55, 4.39, 13.35, 13.14, + 3.61, 2.51, + 2.88, 2.83, 3.07, 4.81, 2.55, 2.57, 2.73, 2.84, 2.44, 3.01, 4.95, 2.63, 3.06, 3.77, 2.88, 3.44, 4.72, 2.91, + 3.21, + 4.47, 2.38, 2.31, 2.9, 4.26, 3.57, 2.31, 2.24, 2.81, 4.37, 2.67, 2.8, 2.74, 2.16, 2.79, 2.88, 5.79, 2.75, + 2.93, 2.88, + 2.31, 2.72, 2.39, 2.6, 2.55, 2.58, 4.29, 2.69, 2.86, 2.09, 3.12, 2.31, 2.28, 2.87, 6.97, 3.1, 2.35, 3.4, + 2.61, 2.62 ] try: - df = pd.read_excel(self.RESULT_EXCEL.get("all",None), sheet_name='Bandwidth Contention Analysis', header=0) + df = pd.read_excel(self.RESULT_EXCEL.get("all", None), sheet_name='Bandwidth Contention Analysis', header=0) except FileNotFoundError: - logging.error("File %s not found.", self.RESULT_EXCEL.get("all",None)) + logging.error("File %s not found.", self.RESULT_EXCEL.get("all", None)) return for index, row in df.iterrows(): @@ -276,9 +282,9 @@ class TestAdvisorCmdSingleAscendPtNoCompare(TestCase): test_pattern = ["all", "computation"] for pattern in test_pattern: try: - df = pd.read_excel(self.RESULT_EXCEL.get(pattern,None), sheet_name='AICPU operator', header=0) + df = pd.read_excel(self.RESULT_EXCEL.get(pattern, None), sheet_name='AICPU operator', header=0) except FileNotFoundError: - logging.error("File %s not found.", self.RESULT_EXCEL.get(pattern,None)) + logging.error("File %s not found.", self.RESULT_EXCEL.get(pattern, None)) return for index, row in df.iterrows(): @@ -293,7 +299,7 @@ class TestAdvisorCmdSingleAscendPtNoCompare(TestCase): self.assertEqual(output_formats[index], row["output_formats"]) self.assertEqual(stack_info[index], math.isnan(row["stack_info"])) - soup = BeautifulSoup(open(self.RESULT_HTML.get(pattern,None)), 'html.parser') + soup = BeautifulSoup(open(self.RESULT_HTML.get(pattern, None)), 'html.parser') for h2 in soup.find_all('h2'): if h2.contents[0] == "AICPU Issues": div_content = h2.next.next.next @@ -324,17 +330,17 @@ class TestAdvisorCmdSingleAscendPtNoCompare(TestCase): self.assertEqual(b_names[b_index], b_content.text) def test_Affinity_API(self): - affinity_api = ["torch_npu.npu_confusion_transpose","torch_npu.optim.NpuFusedAdamW"] - code_stacks = [True,True] - stack_called_counts = [True,True] + affinity_api = ["torch_npu.npu_confusion_transpose", "torch_npu.optim.NpuFusedAdamW"] + code_stacks = [True, True] + stack_called_counts = [True, True] ignore_api = ["torch_npu.optim.NpuFusedAdamW", "torch_npu.npu_confusion_transpose"] test_pattern = ["all", "schedule"] for pattern in test_pattern: try: - df = pd.read_excel(self.RESULT_EXCEL.get(pattern,None), sheet_name='Affinity apis', header=0) + df = pd.read_excel(self.RESULT_EXCEL.get(pattern, None), sheet_name='Affinity apis', header=0) except FileNotFoundError: - logging.error("File %s not found.", self.RESULT_EXCEL.get(pattern,None)) + logging.error("File %s not found.", self.RESULT_EXCEL.get(pattern, None)) return for index, row in df.iterrows(): @@ -342,12 +348,12 @@ class TestAdvisorCmdSingleAscendPtNoCompare(TestCase): self.assertEqual(code_stacks[index], math.isnan(row["Code stacks"])) self.assertEqual(stack_called_counts[index], math.isnan(row["Stack called counts"])) - soup = BeautifulSoup(open(self.RESULT_HTML.get(pattern,None)), 'html.parser') + soup = BeautifulSoup(open(self.RESULT_HTML.get(pattern, None)), 'html.parser') for h2 in soup.find_all('h2'): if h2.contents[0] == "Affinity API Issues": div_content = h2.next.next.next - self.assertEqual(ignore_api[0],div_content.contents[-2].contents[-2].text) - self.assertEqual(ignore_api[1],div_content.contents[-2].contents[-4].text) + self.assertEqual(ignore_api[0], div_content.contents[-2].contents[-2].text) + self.assertEqual(ignore_api[1], div_content.contents[-2].contents[-4].text) def test_operator_dispatch(self): issues = ["operator dispatch"] @@ -364,9 +370,9 @@ class TestAdvisorCmdSingleAscendPtNoCompare(TestCase): test_pattern = ["all", "schedule"] for pattern in test_pattern: try: - df = pd.read_excel(self.RESULT_EXCEL.get(pattern,None), sheet_name='operator dispatch', header=0) + df = pd.read_excel(self.RESULT_EXCEL.get(pattern, None), sheet_name='operator dispatch', header=0) except FileNotFoundError: - logging.error("File %s not found.", self.RESULT_EXCEL.get(pattern,None)) + logging.error("File %s not found.", self.RESULT_EXCEL.get(pattern, None)) return for index, row in df.iterrows(): self.assertEqual(issues[index], row["Issues"]) @@ -374,7 +380,7 @@ class TestAdvisorCmdSingleAscendPtNoCompare(TestCase): self.assertEqual(counts[index], row["counts"]) self.assertEqual(total_time[index], round(row["total time"], 4)) - soup = BeautifulSoup(open(self.RESULT_HTML.get(pattern,None)), 'html.parser') + soup = BeautifulSoup(open(self.RESULT_HTML.get(pattern, None)), 'html.parser') for h2 in soup.find_all('h2'): if h2.contents[0] == "Operator Dispatch Issues": div_content = h2.next.next.next @@ -391,5 +397,3 @@ class TestAdvisorCmdSingleAscendPtNoCompare(TestCase): self.assertEqual(t1_issue[row_index - 1], row.find_all('td')[0].text) self.assertEqual(t1_counts[row_index - 1], row.find_all('td')[1].text) self.assertEqual(t1_elapsed_time[row_index - 1], row.find_all('td')[2].text) - - diff --git a/profiler/test/st/advisor/utils.py b/profiler/test/st/advisor/utils.py index 66718f388224eedaa1d8deff4bc7ddf01b32115d..2293907960bd36504a1485a6e91a0b3525be7dff 100644 --- a/profiler/test/st/advisor/utils.py +++ b/profiler/test/st/advisor/utils.py @@ -6,11 +6,13 @@ import subprocess RE_EXCEL_MATCH_EXP = r"^mstt_advisor_\d{1,20}\.xlsx" RE_HTML_MATCH_EXP = r"^mstt_advisor_\d{1,20}\.html" + def execute_cmd(cmd): - logging.info('Execute command:%s'," ".join(cmd)) + logging.info('Execute command:%s', " ".join(cmd)) completed_process = subprocess.run(cmd, capture_output=True, shell=False, check=True) return completed_process.returncode + def get_files(out_path): dirs = os.listdir(out_path) result_html = {} @@ -44,6 +46,3 @@ def get_files(out_path): result_html[pattern] = os.path.join(files_out_path, newest_html_file) result_excel[pattern] = os.path.join(log_dir, newest_excel_file) return result_html, result_excel - - - diff --git a/profiler/test/ut/advisor/common/test_enum_params_parser.py b/profiler/test/ut/advisor/common/test_enum_params_parser.py index 8e5ddb680444c944898201bb58f7b71a520b924b..c27a632f64c844eaa4fa079214d87a2caae022ca 100644 --- a/profiler/test/ut/advisor/common/test_enum_params_parser.py +++ b/profiler/test/ut/advisor/common/test_enum_params_parser.py @@ -17,7 +17,7 @@ class TestEnumParamsParser(unittest.TestCase): def setUp(self) -> None: self.enum_params_parser = EnumParamsParser() - self.argument_keys = sorted(["cann_version", "torch_version", "analysis_dimensions", "profiling_type"]) + self.argument_keys = sorted(["cann_version", "torch_version", "analysis_dimensions", "profiling_type", "mindspore_version"]) self.env_keys = ["ADVISOR_ANALYZE_PROCESSES", "DISABLE_PROFILING_COMPARISON", "DISABLE_AFFINITY_API"] def test_get_keys(self):