diff --git a/profiler/advisor/advisor_backend/cluster_advice/cluster_advice_base.py b/profiler/advisor/advisor_backend/cluster_advice/cluster_advice_base.py index 60e5a75482a5b183612fbae08f4e28e2fa088501..a9dbf4c05020a671bcc1b6ee0cbb18620475a0ee 100644 --- a/profiler/advisor/advisor_backend/cluster_advice/cluster_advice_base.py +++ b/profiler/advisor/advisor_backend/cluster_advice/cluster_advice_base.py @@ -14,15 +14,17 @@ # limitations under the License. import os - from abc import abstractmethod + from advice_base import AdviceBase from cluster_analysis import Interface + from profiler.advisor.advisor_backend.logger import Logger from profiler.prof_common.constant import Constant logger = Logger() + class ClusterAdviceBase(AdviceBase): def __init__(self, collection_path: str): super().__init__(collection_path) @@ -67,4 +69,4 @@ class ClusterAdviceBase(AdviceBase): def output(self): """ output relevant data - """ \ No newline at end of file + """ diff --git a/profiler/advisor/advisor_backend/cluster_advice/cluster_pipeline_advice.py b/profiler/advisor/advisor_backend/cluster_advice/cluster_pipeline_advice.py index 47fd73d0ab2ac9e76947f7c472dc606105dc80c4..38e2e766b0fa10da55a4663d2e07dc9b18fc5c3e 100644 --- a/profiler/advisor/advisor_backend/cluster_advice/cluster_pipeline_advice.py +++ b/profiler/advisor/advisor_backend/cluster_advice/cluster_pipeline_advice.py @@ -13,31 +13,31 @@ # See the License for the specific language governing permissions and # limitations under the License. +import multiprocessing import os import time -import multiprocessing -from typing import Dict -from typing import Optional -from typing import Deque -from typing import List -from typing import Tuple from collections import defaultdict from collections import deque -from decimal import Decimal from dataclasses import dataclass +from decimal import Decimal +from typing import Deque +from typing import Dict +from typing import List +from typing import Optional +from typing import Tuple +from cluster_advice.cluster_advice_base import ClusterAdviceBase +from cluster_data_preprocess.pytorch_data_preprocessor import PytorchDataPreprocessor from common_func_advisor.constant import Constant from common_func_advisor.trace_view_preprocessor import FineTraceViewData from common_func_advisor.trace_view_preprocessor import TraceViewPreProcessor -from cluster_advice.cluster_advice_base import ClusterAdviceBase -from cluster_data_preprocess.pytorch_data_preprocessor import PytorchDataPreprocessor + from profiler.advisor.advisor_backend.logger import Logger from profiler.prof_common.file_manager import FileManager logger = Logger() - @dataclass class PipelineTimeSlice: start: str = "" @@ -124,6 +124,7 @@ class PipelineTraceViewer: return data + class ClusterPipelineAdvice(ClusterAdviceBase): BUBBLE = "Bubble" STAGE = "Stage" @@ -139,22 +140,6 @@ class ClusterPipelineAdvice(ClusterAdviceBase): self.cur_bottleneck = {} self.cur_advices = "" - - @staticmethod - def _align_trace_bound(results: List) -> None: - """ - align all rank trace bound for better visualization - """ - start_list, end_list = [], [] - for res in results: - start_list.append(res[0].start) - end_list.append(res[-1].end) - - # update all rank trace bound - for res in results: - res[0].start = min(start_list) - res[-1].end = max(end_list) - @staticmethod def load_trace_view_data(json_path) -> Optional[FineTraceViewData]: """ @@ -272,6 +257,21 @@ class ClusterPipelineAdvice(ClusterAdviceBase): return res + @staticmethod + def _align_trace_bound(results: List) -> None: + """ + align all rank trace bound for better visualization + """ + start_list, end_list = [], [] + for res in results: + start_list.append(res[0].start) + end_list.append(res[-1].end) + + # update all rank trace bound + for res in results: + res[0].start = min(start_list) + res[-1].end = max(end_list) + def run(self) -> dict: """ Unified entrance interface @@ -291,8 +291,8 @@ class ClusterPipelineAdvice(ClusterAdviceBase): process all rank profiling data by using multi-process """ start_time = time.time() - logger.info("Start to process %s rank profiling data with %s workers." - ,str(len(self.rank_prof_dirs)),str(self.worker_num)) + logger.info("Start to process %s rank profiling data with %s workers.", + str(len(self.rank_prof_dirs)), str(self.worker_num)) with multiprocessing.Pool(self.worker_num) as pool: results = pool.map(self.work, self.rank_prof_dirs.items()) @@ -302,7 +302,7 @@ class ClusterPipelineAdvice(ClusterAdviceBase): else: self.cur_data += PipelineTraceViewer().gen_stage_bubble_trace_data(rank_id, res) time_cost = time.time() - start_time - logger.info("Pipline view data process finished, cost %2f s.",time_cost) + logger.info("Pipline view data process finished, cost %2f s.", time_cost) def work(self, kv: Tuple[int, str]) -> Tuple[List[PipelineTimeSlice], bool]: """ @@ -310,29 +310,29 @@ class ClusterPipelineAdvice(ClusterAdviceBase): """ show_fp_bp = False rank_id, rank_prof_dir = kv - logger.info("[Rank %s] Start to process rank profiling data.",rank_id) + logger.info("[Rank %s] Start to process rank profiling data.", rank_id) json_path = os.path.join(rank_prof_dir, Constant.ASCEND_PROFILER_OUTPUT, Constant.TRACE_VIEW_JSON) fine_data = self.load_trace_view_data(json_path) if not fine_data.hcom_ops or not fine_data.hcom_tids: logger.error("[Rank %s] No hcom send recv ops found, make sure the trace view data is " - "pipeline parallel sense.",str(rank_id)) + "pipeline parallel sense.", str(rank_id)) return [], show_fp_bp timeslice_list = self.get_pipeline_timeslice(fine_data.hcom_ops, fine_data.hcom_tids, fine_data.min_ts, fine_data.max_ts) if not fine_data.fp_ops or not fine_data.bp_ops: logger.info("[Rank %s] No frameWork data in trace view, only show stage and bubble." - ,str(rank_id)) + , str(rank_id)) elif len(fine_data.hcom_tids) > 1: logger.warning("[Rank %s] More than one hcom tid found, only show stage and bubble." - ,str(rank_id)) + , str(rank_id)) else: logger.info("[Rank %s] Found frameWork data in trace view, show fp bp and bubble." - ,rank_id) + , rank_id) bp_ops = self.get_fp_bp_bound_ops(fine_data) self.update_stage_fp_bp(timeslice_list, bp_ops) show_fp_bp = True - logger.info("[Rank %s] Rank profiling data process finished.",str(rank_id)) + logger.info("[Rank %s] Rank profiling data process finished.", str(rank_id)) return timeslice_list, show_fp_bp @@ -373,7 +373,7 @@ class ClusterPipelineAdvice(ClusterAdviceBase): if rank_id in data_map: rank_prof_dirs[rank_id] = data_map[rank_id] else: - logger.warning('Rank %s not found in %s',str(self.collection_path)) + logger.warning('Rank %s not found in %s', str(self.collection_path)) return rank_prof_dirs diff --git a/profiler/advisor/advisor_backend/common_func_advisor/trace_view_json.py b/profiler/advisor/advisor_backend/common_func_advisor/trace_view_json.py index a6337cd5798e6367e0e61e241ab54fa89ee28b60..7fb75f065e5605e2d6a6036714cb381549fa6038 100644 --- a/profiler/advisor/advisor_backend/common_func_advisor/trace_view_json.py +++ b/profiler/advisor/advisor_backend/common_func_advisor/trace_view_json.py @@ -23,11 +23,12 @@ from typing import List import pandas as pd -from profiler.prof_common.file_manager import FileManager from profiler.advisor.advisor_backend.logger import Logger +from profiler.prof_common.file_manager import FileManager logger = Logger() + @dataclass class TraceObj: ph: str = "" @@ -97,21 +98,21 @@ class TraceViewJson: self.torch_2_npu_flow_events: Dict[str, FlowEvent] = dict() traces = FileManager.read_json_file(path) self._load_obj(traces) - + def get_call_stack(self, data: pd.DataFrame, index_id: int, ts_col: str) -> str: if ts_col not in data.columns.tolist(): - logger.error("No %s col found in data columns.",str(ts_col)) + logger.error("No %s col found in data columns.", str(ts_col)) return "" row = data.loc[index_id] timestamp = row[ts_col] flow_event = self.get_torch_2_npu_flow_event(timestamp) if not flow_event.valid(): - logger.error("Get flow event failed for pattern %s.",str(row['pattern'])) + logger.error("Get flow event failed for pattern %s.", str(row['pattern'])) return "" flow_event_s_key = flow_event.s_point_ts python_dur_events = self.get_python_dur_events_contain_ts(flow_event_s_key) if not python_dur_events: - logger.error("No python dur event found for pattern %s.",str(row['pattern'])) + logger.error("No python dur event found for pattern %s.", str(row['pattern'])) return "" # 保持新老版本callstack兼容性 if python_dur_events[0].args.get("Call stack"): @@ -126,7 +127,7 @@ class TraceViewJson: def get_torch_2_npu_flow_event(self, end_time) -> FlowEvent: if not self.torch_2_npu_flow_events or not self.torch_2_npu_flow_events.get(end_time): - logger.error("Find flow event failed for ts: %s",str(end_time)) + logger.error("Find flow event failed for ts: %s", str(end_time)) return FlowEvent() return self.torch_2_npu_flow_events.get(end_time) @@ -151,7 +152,7 @@ class TraceViewJson: for check_process in check_processes: if check_process in self.processes: continue - logger.error("%s process not found in json.",str(check_process)) + logger.error("%s process not found in json.", str(check_process)) return False return True diff --git a/profiler/advisor/advisor_backend/compute_advice/npu_fused/csv_analyzer.py b/profiler/advisor/advisor_backend/compute_advice/npu_fused/csv_analyzer.py index 8ae109856a3b8719d8d7fef2ff15ca7a1270eccc..c480640d091e06ba4f26ee6388db7e72c5670342 100644 --- a/profiler/advisor/advisor_backend/compute_advice/npu_fused/csv_analyzer.py +++ b/profiler/advisor/advisor_backend/compute_advice/npu_fused/csv_analyzer.py @@ -20,6 +20,7 @@ import numpy as np from common_func.path_manager import PathManager from common_func_advisor.constant import Constant + from .op_perf import OpPerfFactory @@ -27,22 +28,6 @@ class CSVAnalyzer: def __init__(self, path) -> None: self._path = path - def process(self): - PathManager.check_path_readable(self._path) - df = pd.read_csv(self._path, dtype={"Start Time(us)": str}) - # 分析是否存在可融合的算子 - op_type_list = df["Type"].tolist() - duration_list = df["Duration(us)"].tolist() - start_times = df["Start Time(us)"].tolist() - # 去除末尾的\t分隔符 - start_times = [start_time[:-1] for start_time in start_times] - result_list = [] - for pattern in Constant.PATTERN_DICT.keys(): - result_list.extend(self.find_all_sub_lists(op_type_list, duration_list, start_times, pattern)) - data_frame = pd.DataFrame(result_list) - data_frame.columns = ["pattern_name", "pattern", "len", "count", "duration sum(us)", "op durations(us)", - "index", "first_timestamp"] - return data_frame @staticmethod def find_all_sub_lists(op_type_list, duration_list, start_times, expect_sub_list): @@ -81,3 +66,20 @@ class CSVAnalyzer: repeated_sublists.append([pattern_name, expect_sub_list, 0, 0, 0, 0, 0, 0]) # 返回所有重复的子列表 return repeated_sublists + + def process(self): + PathManager.check_path_readable(self._path) + df = pd.read_csv(self._path, dtype={"Start Time(us)": str}) + # 分析是否存在可融合的算子 + op_type_list = df["Type"].tolist() + duration_list = df["Duration(us)"].tolist() + start_times = df["Start Time(us)"].tolist() + # 去除末尾的\t分隔符 + start_times = [start_time[:-1] for start_time in start_times] + result_list = [] + for pattern in Constant.PATTERN_DICT.keys(): + result_list.extend(self.find_all_sub_lists(op_type_list, duration_list, start_times, pattern)) + data_frame = pd.DataFrame(result_list) + data_frame.columns = ["pattern_name", "pattern", "len", "count", "duration sum(us)", "op durations(us)", + "index", "first_timestamp"] + return data_frame diff --git a/profiler/advisor/advisor_backend/compute_advice/npu_fused/op_perf.py b/profiler/advisor/advisor_backend/compute_advice/npu_fused/op_perf.py index 7bcbed5a75807b57a55787c743cfaaff55a68589..87ed2bac3b846dd89d08f8169710521516b7d8ad 100644 --- a/profiler/advisor/advisor_backend/compute_advice/npu_fused/op_perf.py +++ b/profiler/advisor/advisor_backend/compute_advice/npu_fused/op_perf.py @@ -85,15 +85,15 @@ class OpPerf: self.aiv_mte3_ratio = op_row.get("aiv_mte3_ratio") self.aiv_icache_miss_rate = op_row.get("aiv_icache_miss_rate") self.cube_utilization = op_row.get("cube_utilization( %)") - + @staticmethod def get_dtype_size(dtype_str: str): return Constant.DTYPE_SIZE_MAP.get(dtype_str.lower(), 0) - + @staticmethod def get_element_count(shape: list): return functools.reduce(lambda x, y: int(x) * int(y), shape) - + @staticmethod def shape_to_tuple(shape_str: str) -> tuple: if not isinstance(shape_str, str): @@ -110,7 +110,7 @@ class OpPerf: elements = tuple(int(element) if "" != element else 0 for element in elements) shape_result.append(elements) return tuple(shape_result) - + @staticmethod def dtype_to_tuple(dtypes_str: str) -> tuple: if not isinstance(dtypes_str, str): @@ -121,10 +121,10 @@ class OpPerf: return [] pairs = split_dtypes.split(';') return tuple(pairs) - + def get_mac_ratio(self): return self.aic_mac_ratio - + def get_size(self, shapes_str, dtypes_str): shapes = self.shape_to_tuple(shapes_str) dtypes = self.dtype_to_tuple(dtypes_str) @@ -140,7 +140,7 @@ class OpPerf: dtype_size = self.get_dtype_size(dtypes[index]) all_size += element_count * dtype_size return all_size - + def get_calc_size(self): # input and output bytes (MB) if not self.input_shapes or not self.output_shapes: @@ -149,14 +149,16 @@ class OpPerf: intput_size = self.get_size(self.input_shapes, self.input_data_types) output_size = self.get_size(self.output_shapes, self.output_data_types) return (intput_size + output_size) / (Constant.BYTE_UNIT_TRANS * Constant.BYTE_UNIT_TRANS) - + def get_throughput(self): - # throughput(GB/s) + # throughput bytes (GB/s) if not self.task_duration or abs(self.task_duration) < 1e-6: print("[ERROR] There is no task_duration, do not assess vector op performance.") return 0 - return self.row[Constant.TITLE.SIZE] / Constant.BYTE_UNIT_TRANS / self.task_duration * Constant.UNIT_TRANS * Constant.UNIT_TRANS - + return (self.row[ + Constant.TITLE.SIZE] / Constant.BYTE_UNIT_TRANS + / self.task_duration * Constant.UNIT_TRANS * Constant.UNIT_TRANS) + def get_perf_color(self): return PerfColor.WHITE diff --git a/profiler/advisor/advisor_backend/logger.py b/profiler/advisor/advisor_backend/logger.py index 3b72d157a28a0a2953cf99bb90d0d31539ce2be9..5fb8b5d407d1cf139be636eea6925d4d064d44f2 100644 --- a/profiler/advisor/advisor_backend/logger.py +++ b/profiler/advisor/advisor_backend/logger.py @@ -15,6 +15,7 @@ import logging + class Logger: def __init__(self): if not hasattr(self, 'logger'): @@ -35,4 +36,3 @@ class Logger: def critical(self, message): self.logger.critical(message) - diff --git a/profiler/advisor/advisor_backend/timeline_advice/op_schedule_advice.py b/profiler/advisor/advisor_backend/timeline_advice/op_schedule_advice.py index 9e868784c7962f79e6f398160fedd3e36decebf2..5bf2fed3cbe6f4e21ffd94cdcd1d5b290b587881 100644 --- a/profiler/advisor/advisor_backend/timeline_advice/op_schedule_advice.py +++ b/profiler/advisor/advisor_backend/timeline_advice/op_schedule_advice.py @@ -14,11 +14,13 @@ # limitations under the License. import logging from decimal import Decimal + from common_func_advisor.constant import Constant from timeline_advice.timeline_advice_base import TimelineAdviceBase logger = logging.getLogger() + class OpScheduleAdvice(TimelineAdviceBase): def __init__(self, collection_path: str): super().__init__(collection_path) @@ -46,7 +48,7 @@ class OpScheduleAdvice(TimelineAdviceBase): merge_data = list() merge_data.extend(cpt_data) merge_data.extend(free_data) - merge_data.sort(key=lambda x : Decimal(x.get("ts"))) + merge_data.sort(key=lambda x: Decimal(x.get("ts"))) idx = free_idx = 0 while idx < len(merge_data) and free_idx < len(op_free): entry = merge_data[idx] @@ -62,10 +64,10 @@ class OpScheduleAdvice(TimelineAdviceBase): if free_ratio < 0.2: return self.cur_bottleneck = f"NPU Utilication: {round(free_ratio * 100, 2)}%, " \ - f"NPU Free Utilization: {round(cpt_ratio * 100, 2)}%." + f"NPU Free Utilization: {round(cpt_ratio * 100, 2)}%." if len(self.preparse_data[self.PreParseType.SYNCHRONIZE]) > 1: self.cur_advice = f"Device synchronize {len(self.preparse_data[self.PreParseType.SYNCHRONIZE])} times, " \ - "try to reduce synchronization statements to alleviate the bottleneck of operator delivery.\n" + "try to reduce synchronization statements to alleviate the bottleneck of operator delivery.\n" small_op_num = self.small_op_block(op_free, op_dur) small_op_ratio = small_op_num / len(op_dur) if op_dur else 0.0 if small_op_ratio > Constant.SMALL_OP_NUM_RATIO: 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 0bcf9a8f68787fc42d1ed5f9e34eafd42e5cbb21..8a72732e0ab15ba5ec549482865528fc56de9eda 100644 --- a/profiler/advisor/advisor_backend/timeline_advice/timeline_advice_base.py +++ b/profiler/advisor/advisor_backend/timeline_advice/timeline_advice_base.py @@ -13,18 +13,21 @@ # See the License for the specific language governing permissions and # limitations under the License. +import logging +import os +import json + from abc import abstractmethod from collections import defaultdict -import json -import os -import logging from advice_base import AdviceBase + from profiler.prof_common.file_manager import FileManager logger = logging.getLogger() logger.setLevel(logging.INFO) + class TimelineAdviceBase(AdviceBase): class PreParseType: OPTIMIZER = 0 @@ -53,21 +56,21 @@ class TimelineAdviceBase(AdviceBase): check whether input path is valid """ if not os.path.exists(self.collection_path): - logger.error("Path: %s is not exist.",str(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") or self.collection_path.endswith("ascend_ms")): + (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."\ - ,str(os.path.join(self.collection_path, "ASCEND_PROFILER_OUTPUT"))) + logger.error("trace_view.json is not exist in the Path: %s.", + str(os.path.join(self.collection_path, "ASCEND_PROFILER_OUTPUT"))) return False elif os.path.isfile(self.collection_path) and os.path.basename(self.collection_path) == "trace_view.json": self.trace_view_path = self.collection_path else: logger.error("Please input ascend_pt or trace_view.json.") return False - logger.info("Start to analyse the target file: %s",str(self.trace_view_path)) + logger.info("Start to analyse the target file: %s", str(self.trace_view_path)) return True @abstractmethod diff --git a/profiler/advisor/analyzer/analyzer_controller.py b/profiler/advisor/analyzer/analyzer_controller.py index 879b04ecb38130d59744b137d646880ea90c9d69..b239748bab82651826d2ac3dbcf19b0461dc4100 100644 --- a/profiler/advisor/analyzer/analyzer_controller.py +++ b/profiler/advisor/analyzer/analyzer_controller.py @@ -309,20 +309,20 @@ class AnalyzerController: output_path: analysis output path(including html and xlsx). Example: - >>> # initialize a global analyzer controller - >>> analyzer_controller = AnalyzerController() - >>> analysis_kwargs = dict(advisor_analyze_processes=2, disable_profiling_comparison=True) - >>> - >>> async_analysis_process = analyzer_controller.async_do_analysis(Interface.all_dimension, **analysis_kwargs) - >>> - >>> # query the job status every second - >>> while True: - >>> response = analyzer_controller.get_response_by_pid(async_analysis_process.pid) - >>> print(f'analysis response is {response}') - >>> if response.get("status") in ["success", "failed"]: - >>> async_analysis_process.join() - >>> break - >>> time.sleep(1) + >>> # initialize a global analyzer controller + >>> analyzer_controller = AnalyzerController() + >>> analysis_kwargs = dict(advisor_analyze_processes=2, disable_profiling_comparison=True) + >>> + >>> async_analysis_process = analyzer_controller.async_do_analysis(Interface.all_dimension, **analysis_kwargs) + >>> + >>> # query the job status every second + >>> while True: + >>> response = analyzer_controller.get_response_by_pid(async_analysis_process.pid) + >>> print(f'analysis response is {response}') + >>> if response.get("status") in ["success", "failed"]: + >>> async_analysis_process.join() + >>> break + >>> time.sleep(1) """ kwargs["is_async_analysis"] = True diff --git a/profiler/advisor/analyzer/base_analyzer.py b/profiler/advisor/analyzer/base_analyzer.py index 17fa7fd3fad9b6f6837c1fe701882c0f060edc3f..0391eb88a28ee2d63f8c139709fdf6bbcbf5d9bf 100644 --- a/profiler/advisor/analyzer/base_analyzer.py +++ b/profiler/advisor/analyzer/base_analyzer.py @@ -114,12 +114,12 @@ class BaseAnalyzer(VersionControl, metaclass=ABCMeta): else: for _, dirs, __ in os.walk(self.collection_path): is_found_type = False - for dir in dirs: - if dir.endswith(ASCEND_MS): + for direction in dirs: + if direction.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): + elif direction.endswith(ASCEND_PT): profiling_type = [elem for elem in profiling_type_list if Constant.PYTORCH in elem][0] is_found_type = True break @@ -142,9 +142,9 @@ class BaseAnalyzer(VersionControl, metaclass=ABCMeta): 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)) + for direction in dirs: + if direction.endswith(ASCEND_MS): + ascend_dirs.append(os.path.join(root, direction)) if ascend_dirs: ascend_dir = ascend_dirs[0] for file_name in os.listdir(ascend_dir): diff --git a/profiler/advisor/analyzer/computation/ai_core_freq/ai_core_freq_checker.py b/profiler/advisor/analyzer/computation/ai_core_freq/ai_core_freq_checker.py index 798d41e16dbf0f28ad4199907674edd72498d1ef..c2b7f246b025de315b67484fd57eaf02c5e9ee7a 100644 --- a/profiler/advisor/analyzer/computation/ai_core_freq/ai_core_freq_checker.py +++ b/profiler/advisor/analyzer/computation/ai_core_freq/ai_core_freq_checker.py @@ -75,9 +75,9 @@ class AICoreFreqChecker: if self.decrease_freq_ops: # 按算子总耗时和降频比率 降序排列 - self.decrease_freq_ops.sort(key = + self.decrease_freq_ops.sort(key= lambda x: (x[self.TOTAL_DURATION_INDEX], x[self.DECREASE_FREQ_RATIO_INDEX]), - reverse = True) + reverse=True) if not self.ai_core_freq_issues: return diff --git a/profiler/advisor/analyzer/computation/aicpu/aicpu_checker.py b/profiler/advisor/analyzer/computation/aicpu/aicpu_checker.py index 83f3b6acc68fa5ab10693f2136368a1a433066d0..fc8130f7a305b10a0178f9187c2379b24536e73e 100644 --- a/profiler/advisor/analyzer/computation/aicpu/aicpu_checker.py +++ b/profiler/advisor/analyzer/computation/aicpu/aicpu_checker.py @@ -23,8 +23,9 @@ from profiler.advisor.dataset.dataset import Dataset from profiler.advisor.dataset.profiling.profiling_dataset import ProfilingDataset from profiler.advisor.dataset.timeline_event_dataset import ComputationAnalysisDataset from profiler.prof_common.additional_args_manager import AdditionalArgsManager -from profiler.prof_common.file_manager import FileManager from profiler.prof_common.constant import Constant +from profiler.prof_common.file_manager import FileManager + class AicpuChecker(OperatorChecker): _CHECKER = "aicpu operator" diff --git a/profiler/advisor/analyzer/computation/operator_checker.py b/profiler/advisor/analyzer/computation/operator_checker.py index 445f09cff15291c0823b184b94e1418ee69c5268..1b03dd25f8351011493ab06d049f76076c138570 100644 --- a/profiler/advisor/analyzer/computation/operator_checker.py +++ b/profiler/advisor/analyzer/computation/operator_checker.py @@ -134,23 +134,6 @@ class OperatorChecker(VersionControl): ) return OptimizeRecord(optimization_item, statistics_item) - def _get_description(self, description, op_type_list=None): - if not op_type_list: - return description - - desc_suffix = [] - for i, _ in enumerate(op_type_list): - if i % 3 == 0 and i != 0: - desc_suffix.append("\n") - - desc_suffix.append(f"{op_type_list[i]}") - - if i < len(op_type_list) - 1: - desc_suffix.append(", ") - - description += "".join(desc_suffix) - return description - def pre_check(self, profiling_data) -> bool: return True @@ -335,3 +318,20 @@ class OperatorChecker(VersionControl): logger.warning(self.SKIP_CHECK_MSG, self._CHECKER, "op summary") return False return True + + def _get_description(self, description, op_type_list=None): + if not op_type_list: + return description + + desc_suffix = [] + for i, _ in enumerate(op_type_list): + if i % 3 == 0 and i != 0: + desc_suffix.append("\n") + + desc_suffix.append(f"{op_type_list[i]}") + + if i < len(op_type_list) - 1: + desc_suffix.append(", ") + + description += "".join(desc_suffix) + return description diff --git a/profiler/advisor/analyzer/computation/profiling_analyzer.py b/profiler/advisor/analyzer/computation/profiling_analyzer.py index 97154bb9f7bfc11d8299b65bdd6ce050745ba41c..ccf6711399541d72a2b8f1dabcceafa5a8db7671 100644 --- a/profiler/advisor/analyzer/computation/profiling_analyzer.py +++ b/profiler/advisor/analyzer/computation/profiling_analyzer.py @@ -78,7 +78,7 @@ class ProfilingAnalyzer(BaseAnalyzer, ABC): return self.result - def get_priority(self,max_mem_op_dur): + def get_priority(self, max_mem_op_dur): if "aicpu" not in max_mem_op_dur.__class__.__name__.lower(): return PriorityBackgroundColor.low diff --git a/profiler/advisor/analyzer/memory/memory_analyzer.py b/profiler/advisor/analyzer/memory/memory_analyzer.py index 939e2de90c634ee6cca584dca345111dce26bb7b..a6ad3258d3e722fb36df9ddfd2a8b5185caf6e87 100644 --- a/profiler/advisor/analyzer/memory/memory_analyzer.py +++ b/profiler/advisor/analyzer/memory/memory_analyzer.py @@ -15,11 +15,11 @@ import logging from profiler.advisor.analyzer.base_analyzer import BaseAnalyzer -from profiler.advisor.result.result import OptimizeResult from profiler.advisor.analyzer.memory.memory_checker import MemoryOpsChecker -from profiler.advisor.display.html.render import HTMLRender from profiler.advisor.dataset.timeline_event_dataset import ScheduleAnalysisDataset from profiler.advisor.display.html.priority_background_color import PriorityBackgroundColor +from profiler.advisor.display.html.render import HTMLRender +from profiler.advisor.result.result import OptimizeResult logger = logging.getLogger() @@ -39,7 +39,8 @@ class MemoryAnalyzer(BaseAnalyzer): memory_checker = MemoryOpsChecker() memory_checker.check_memory_ops(self.dataset) memory_checker.make_record(self.result) - memory_checker.make_render(self.html_render, priority=self.get_priority(memory_checker.max_mem_op_dur), rank=kwargs.get("rank")) + memory_checker.make_render(self.html_render, priority=self.get_priority(memory_checker.max_mem_op_dur), + rank=kwargs.get("rank")) return self.result def get_priority(self, max_mem_op_dur): 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 21cf5c4d0b125110a04f334893ce8160b7eb988f..088c8687313fb2945706b4dca60b9c5581436777 100644 --- a/profiler/advisor/analyzer/schedule/fusion_ops/fusion_ops_analyzer.py +++ b/profiler/advisor/analyzer/schedule/fusion_ops/fusion_ops_analyzer.py @@ -12,24 +12,24 @@ # 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 multiprocessing import logging +import multiprocessing +import os import re from tqdm import tqdm from profiler.advisor.analyzer.base_analyzer import BaseAnalyzer -from profiler.advisor.display.prompt.base_prompt import BasePrompt -from profiler.prof_common.constant import Constant from profiler.advisor.common.analyzer_scopes import SupportedScopes from profiler.advisor.common.timeline.event import TimelineEvent +from profiler.advisor.common.timeline.fusion_ops_db import init_timeline_ops_db from profiler.advisor.config.config import Config from profiler.advisor.dataset.timeline_event_dataset import ScheduleAnalysisDataset +from profiler.advisor.display.html.priority_background_color import PriorityBackgroundColor +from profiler.advisor.display.prompt.base_prompt import BasePrompt from profiler.advisor.result.item import OptimizeItem, OptimizeRecord from profiler.advisor.utils.utils import format_timeline_result -from profiler.advisor.common.timeline.fusion_ops_db import init_timeline_ops_db -from profiler.advisor.display.html.priority_background_color import PriorityBackgroundColor +from profiler.prof_common.constant import Constant from profiler.prof_common.additional_args_manager import AdditionalArgsManager logger = logging.getLogger() @@ -96,11 +96,11 @@ class TimelineFusionOpsAnalyzer(BaseAnalyzer): """ if not self.matched_op_stacks: return - + prompt_class = BasePrompt.get_prompt_class(self.__class__.__name__) desc = prompt_class.DESCRIPTION.format(self.cann_version, self.profiling_version, - len(format_timeline_result(self.matched_op_stacks))) + len(format_timeline_result(self.matched_op_stacks))) suggestion = prompt_class.SUGGESTION if self.empty_stacks: desc += prompt_class.EMPTY_STACK_DESCRIPTION @@ -210,7 +210,8 @@ class TimelineFusionOpsAnalyzer(BaseAnalyzer): # by the regex index and then calculate the real index for matched fusion operators in event dataset for left, right in zip(total_ops_split_points, total_ops_split_points[1:]): matched_op_flag = True if (left, right) in matched_pattern_index_tuple else False - matched_ops_list = total_op_name[left: right].strip(Constant.OP_SEP).split(Constant.OP_SEP + Constant.OP_SEP) + matched_ops_list = ( + total_op_name[left: right].strip(Constant.OP_SEP).split(Constant.OP_SEP + Constant.OP_SEP)) op_index.append([matched_op_flag, len(matched_ops_list)]) for i, _ in enumerate(op_index): if i > 0: diff --git a/profiler/advisor/common/analyzer_scopes.py b/profiler/advisor/common/analyzer_scopes.py index 2cad1a3ce7b873ef66730a6c098152853c0b1155..c68acd5edf1c2992ec3311bedd0062938b14c328 100644 --- a/profiler/advisor/common/analyzer_scopes.py +++ b/profiler/advisor/common/analyzer_scopes.py @@ -12,8 +12,9 @@ # 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. -class SupportedScopes: + +class SupportedScopes: # used for specify fourth-level commands and define the key of the result dict # the key defined bellow must be the same as value TIMELINE_FUSION_OPS = "timeline_fusion_ops" diff --git a/profiler/advisor/common/async_analysis_status.py b/profiler/advisor/common/async_analysis_status.py index 3d9a5d7c102ef0a2a20fb4c84cfc00c6a8568899..ee64ebf4de8721da2d81c77203c28c3089ff8cb9 100644 --- a/profiler/advisor/common/async_analysis_status.py +++ b/profiler/advisor/common/async_analysis_status.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -""" + # Copyright (C) 2024-2024. 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. @@ -13,7 +13,6 @@ # 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. -""" class AsyncAnalysisStatus: diff --git a/profiler/advisor/common/enum_params_parser.py b/profiler/advisor/common/enum_params_parser.py index e9a3f6639cda5942ee849b4401268e87378cbc6f..b12937d9d147655b244f9dd7531f2d37126d4e8b 100644 --- a/profiler/advisor/common/enum_params_parser.py +++ b/profiler/advisor/common/enum_params_parser.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -""" + # Copyright (C) 2024-2024. 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. @@ -13,9 +13,9 @@ # 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 logging +import os import typing from profiler.advisor.common.timeline.event import AdvisorDict diff --git a/profiler/advisor/common/graph/graph.py b/profiler/advisor/common/graph/graph.py index f86f5db7f2cec8f51d3daab6b9c6e9d22de44483..3991d67d399f962945c50fa23ddd1e338f65e2ff 100644 --- a/profiler/advisor/common/graph/graph.py +++ b/profiler/advisor/common/graph/graph.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -""" + # Copyright (C) 2024-2024. 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. @@ -13,9 +13,9 @@ # 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 logging -from typing import Dict, List, Tuple, Callable, Any, Optional, Union +from typing import Dict, List, Tuple, Optional, Union, Callable, Any import networkx as nx @@ -33,7 +33,7 @@ class Graph: def __init__(self, nodes: Dict[str, Optional[Union[HostGraphNode, QueryGraphNode]]] = None, edges: List[Tuple[Optional[Union[HostGraphNode, QueryGraphNode]], - Optional[Union[HostGraphNode, QueryGraphNode]]]] = None, + Optional[Union[HostGraphNode, QueryGraphNode]]]] = None, name: str = None): self.name = name self.graph = nx.DiGraph(name=name) diff --git a/profiler/advisor/common/graph/graph_match.py b/profiler/advisor/common/graph/graph_match.py index fbf0a8abe8e049ccb6f9ff2baaa528e94cb3d7e2..f4e86304947aec67a52d97304c2093cb9a4f8769 100644 --- a/profiler/advisor/common/graph/graph_match.py +++ b/profiler/advisor/common/graph/graph_match.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -""" + # Copyright (C) 2024-2024. 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. @@ -13,11 +13,11 @@ # 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 itertools import logging -from functools import lru_cache from collections import deque +from functools import lru_cache from typing import Dict, Generator, List, Callable, Hashable, Tuple import networkx as nx diff --git a/profiler/advisor/common/graph/graph_parser.py b/profiler/advisor/common/graph/graph_parser.py index cffbfa19b4ed99d4597605785ade750982f522b4..718c6af48f07e8012cc86bd91b33a0ab37865599 100644 --- a/profiler/advisor/common/graph/graph_parser.py +++ b/profiler/advisor/common/graph/graph_parser.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -""" + # Copyright (C) 2024-2024. 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. @@ -13,16 +13,16 @@ # 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 logging + import itertools +import logging +import os from collections import deque from dataclasses import dataclass from typing import List, Tuple, Dict -from profiler.prof_common.file_manager import FileManager from profiler.advisor.utils.file import FileOpen +from profiler.prof_common.file_manager import FileManager logger = logging.getLogger() @@ -95,6 +95,7 @@ class HostGraphParser: """ Parse graph metadata from text file """ + def __init__(self, file_path): self.buffer = deque(maxlen=100) self.line_no = 0 @@ -303,7 +304,7 @@ class QueryGraphNode: def __eq__(self, other): return self._op_type == other._op_type and \ - self._id == other._id + self._id == other._id def __hash__(self): return hash(self._op_type + str(self._id)) diff --git a/profiler/advisor/common/profiling/ge_info.py b/profiler/advisor/common/profiling/ge_info.py index 91642f967970fdf27f76754ee4bbd7f4ab4fcc50..927f5d3e714583c4a1aac9b5b72bfd8ef70998b4 100644 --- a/profiler/advisor/common/profiling/ge_info.py +++ b/profiler/advisor/common/profiling/ge_info.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -""" + # Copyright (C) 2024-2024. 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. @@ -13,7 +13,7 @@ # 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 logging import os from typing import Any, List diff --git a/profiler/advisor/common/profiling/msprof.py b/profiler/advisor/common/profiling/msprof.py index 54206bb471afce3842c3fd0faf5d78311d339592..76f51b672d4a6d13f40e30362f3b9900b88c2d80 100644 --- a/profiler/advisor/common/profiling/msprof.py +++ b/profiler/advisor/common/profiling/msprof.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -""" + # Copyright (C) 2024-2024. 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. @@ -13,7 +13,7 @@ # 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 logging from typing import Dict, List diff --git a/profiler/advisor/common/profiling/op_summary.py b/profiler/advisor/common/profiling/op_summary.py index c042509df96c0c8feacb39a56e6f73358cd5d8a9..b1b416888f516559bfcbbfc8a4150c9070bde7fe 100644 --- a/profiler/advisor/common/profiling/op_summary.py +++ b/profiler/advisor/common/profiling/op_summary.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -""" + # Copyright (C) 2024-2024. 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. @@ -13,7 +13,7 @@ # 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 logging from decimal import Decimal from typing import List, Any diff --git a/profiler/advisor/common/profiling/tasktime.py b/profiler/advisor/common/profiling/tasktime.py index 211800585a6b3385e41d009827ec675bfa9df560..e4bc691ff04213ba4cf7b9f8a5868c58c3254dc5 100644 --- a/profiler/advisor/common/profiling/tasktime.py +++ b/profiler/advisor/common/profiling/tasktime.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -""" + # Copyright (C) 2024-2024. 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. @@ -13,7 +13,8 @@ # 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 logging from typing import Dict, List diff --git a/profiler/advisor/common/version_control.py b/profiler/advisor/common/version_control.py index ec30b3be9d84532ff4e8829341dd2da4d3dfc49f..e95168dec243407a2868b4c62f71e01d77a603c6 100644 --- a/profiler/advisor/common/version_control.py +++ b/profiler/advisor/common/version_control.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -""" + # Copyright (C) 2024-2024. 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. @@ -13,7 +13,7 @@ # 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 logging from typing import List diff --git a/profiler/advisor/config/config.py b/profiler/advisor/config/config.py index 0fbca3e57a88576e07476cc9818724d5c1bf5697..518cddb88acc5c2b81f8266a9068c9e859dd8e6e 100644 --- a/profiler/advisor/config/config.py +++ b/profiler/advisor/config/config.py @@ -149,11 +149,6 @@ class Config: except Exception: return "" - def _normalize_path(self, file) -> str: - if not file.startswith("/"): - file = os.path.join(self._work_path, file) - return os.path.abspath(file) - def set_config(self, key, value) -> None: """ set config value @@ -176,11 +171,15 @@ class Config: def set_log_path(self, result_file: str, log_path: str = None): self.log_path = log_path if log_path is not None else os.path.join(self._work_path, "log") os.makedirs(self.log_path, exist_ok=True) - self.config.set("ANALYSE","analysis_result_file",os.path.join(self.log_path, result_file)) + self.config.set("ANALYSE", "analysis_result_file",os.path.join(self.log_path, result_file)) self._analysis_result_file = os.path.join(self.log_path, result_file) def remove_log(self): if self.log_path and os.path.isdir(self.log_path) and not os.listdir(self.log_path): os.rmdir(self.log_path) + def _normalize_path(self, file) -> str: + if not file.startswith("/"): + file = os.path.join(self._work_path, file) + return os.path.abspath(file) diff --git a/profiler/advisor/dataset/profiling/device_info.py b/profiler/advisor/dataset/profiling/device_info.py index 625e4ed0afababe3bbc3ead56891ab4fc5e3693f..dc2eebec1fc372bf9824630bb5cbaf4cf54da487 100644 --- a/profiler/advisor/dataset/profiling/device_info.py +++ b/profiler/advisor/dataset/profiling/device_info.py @@ -1,3 +1,18 @@ +# Copyright (c) 2024, 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. + """ profiling info """ @@ -23,19 +38,6 @@ class DeviceInfoParser: def __init__(self, path) -> None: self._path = path - def parse_data(self) -> bool: - """ - parse profiling data - :return: true for success or false - """ - file_list = get_file_path_from_directory(self._path, lambda x: x.startswith("info.json.")) - if not file_list: - return False - for info in file_list: - if self._parse(info): - return True - return False - @staticmethod def _parse(info_file: str) -> bool: if info_file.endswith("done"): @@ -61,3 +63,18 @@ class DeviceInfoParser: return True logger.error("No ai_core_num in json info file %s", info_file) return False + + def parse_data(self) -> bool: + """ + parse profiling data + :return: true for success or false + """ + file_list = get_file_path_from_directory(self._path, lambda x: x.startswith("info.json.")) + if not file_list: + return False + for info in file_list: + if self._parse(info): + return True + return False + + diff --git a/profiler/advisor/dataset/profiling/profiling_parser.py b/profiler/advisor/dataset/profiling/profiling_parser.py index 73c9fc013ab1c88241d2425f2ff65beb97cfc039..c5576efc0fc694113c926118600b2fc8185a48c2 100644 --- a/profiler/advisor/dataset/profiling/profiling_parser.py +++ b/profiler/advisor/dataset/profiling/profiling_parser.py @@ -59,6 +59,14 @@ class ProfilingParser: except (FloatingPointError, ValueError): return 0.0 + @staticmethod + def parse_from_file(file): + """ + parse from file as a static method + """ + # 实现解析文件的逻辑,这里可以根据需要进行扩展 + return False + @staticmethod def _check_csv_file_format(csv_file_name: str, csv_content: List[List[str]]): if not csv_content: @@ -81,14 +89,6 @@ class ProfilingParser: title_dict[idx] = title.replace(" ", "_") return title_dict - @staticmethod - def parse_from_file(file): - """ - parse from file as a static method - """ - # 实现解析文件的逻辑,这里可以根据需要进行扩展 - return False - def parse_data(self) -> bool: """ Parse task time file diff --git a/profiler/advisor/dataset/timeline_event_dataset.py b/profiler/advisor/dataset/timeline_event_dataset.py index fbac2c5bf0198bf2cec6aef4513ccfaf8aed0396..aad763191a9ab35c6e9eca66304aedb18324c893 100644 --- a/profiler/advisor/dataset/timeline_event_dataset.py +++ b/profiler/advisor/dataset/timeline_event_dataset.py @@ -81,8 +81,9 @@ class BaseTimelineEventDataset: if func_name == FrequencyCollector.__name__: ops_with_task_type = getattr(self, "ops_with_task_type", {}).values() kwargs["ai_core_ops"] = [ - op for op in ops_with_task_type if - op.get(Constant.TASK_TYPE) in [Constant.AI_CORE, Constant.MIX_AIC] + op + for op in ops_with_task_type + if op.get(Constant.TASK_TYPE) in [Constant.AI_CORE, Constant.MIX_AIC] ] return kwargs diff --git a/profiler/advisor/dataset/timeline_op_collector/timeline_op_collector.py b/profiler/advisor/dataset/timeline_op_collector/timeline_op_collector.py index d868acbf59e3a0aec6af99c8cbafcd55d834b8db..fb6a5b1c04d5b5ecbc23fd720eeacf806fc20658 100644 --- a/profiler/advisor/dataset/timeline_op_collector/timeline_op_collector.py +++ b/profiler/advisor/dataset/timeline_op_collector/timeline_op_collector.py @@ -1,3 +1,18 @@ +# Copyright (c) 2024, 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 logging import math import os diff --git a/profiler/advisor/display/prompt/base_prompt.py b/profiler/advisor/display/prompt/base_prompt.py index 2dcacc381e01bd9e84568f77d12b7083170e8d61..2a538f3dbbd7188d551ebd7f04d430792e8deff5 100644 --- a/profiler/advisor/display/prompt/base_prompt.py +++ b/profiler/advisor/display/prompt/base_prompt.py @@ -16,6 +16,7 @@ import importlib from profiler.prof_common.additional_args_manager import AdditionalArgsManager + def split_camel_case(word): result = [] current_word = [] diff --git a/profiler/advisor/display/prompt/en/dynamic_shape_prompt.py b/profiler/advisor/display/prompt/en/dynamic_shape_prompt.py index b350f603f115eb9dad32c49b2d1659ec367df6fe..36e6f5e528ddad9f1130094f8c87ed25efacb870 100644 --- a/profiler/advisor/display/prompt/en/dynamic_shape_prompt.py +++ b/profiler/advisor/display/prompt/en/dynamic_shape_prompt.py @@ -17,8 +17,8 @@ class DynamicShapePrompt(object): RANK_ID = "RANK {} " PROBLEM = "Dynamic Shape Operator" DESCRIPTION = "Found all operators are dynamic shape" - ENABLE_COMPILED_SUGGESTION = "1. Please try to set environment by execute `export HOST_CACHE_CAPACITY=20`.\n." \ - "2. Please place the following code at the entrance of the python script to disable jit compile.\n " \ - "Code: `torch_npu.npu.set_compile_mode(jit_compile=False) \n " \ - "torch_npu.npu.config.allow_internal_format = False`.\n" + ENABLE_COMPILED_SUGGESTION = """1. Please try to set environment by execute `export HOST_CACHE_CAPACITY=20`.\n. + 2. Please place the following code at the entrance of the python script to disable jit compile.\n + Code: `torch_npu.npu.set_compile_mode(jit_compile=False) + torch_npu.npu.config.allow_internal_format = False`.\n""" RELEASE_SUGGESTION = "for details please refer to link : LINK" diff --git a/profiler/advisor/utils/log.py b/profiler/advisor/utils/log.py index 5d9757ebf461d8bece983f56d20770ce9a4c4a17..b260a84925fe89834a5bbc7ef0c4e6b52b970f64 100644 --- a/profiler/advisor/utils/log.py +++ b/profiler/advisor/utils/log.py @@ -1,3 +1,18 @@ +# Copyright (c) 2024, 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. + """ log module """ diff --git a/profiler/advisor/utils/tools.py b/profiler/advisor/utils/tools.py index 2cbcb5e0521d4a947fb8ff6af40e98c32dedab23..83291c953739cbbab47a60208296fc6ae4da9ab4 100644 --- a/profiler/advisor/utils/tools.py +++ b/profiler/advisor/utils/tools.py @@ -1,3 +1,18 @@ +# Copyright (c) 2024, 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. + from functools import partial import click @@ -16,6 +31,12 @@ class ClickAliasedGroup(click.Group): self._alias_dict = {} self._commands = {} + def _decorator_warpper(self, decorator, alias, func=None): + cmd = decorator(func) + self._commands[cmd.name] = alias + self._alias_dict[alias] = cmd.name + return cmd + def command(self, *args, **kwargs): alias = kwargs.pop('alias', None) decorator = super(ClickAliasedGroup, self).command(*args, **kwargs) @@ -32,12 +53,6 @@ class ClickAliasedGroup(click.Group): return partial(self._decorator_warpper, decorator, alias) - def _decorator_warpper(self, decorator, alias, func=None): - cmd = decorator(func) - self._commands[cmd.name] = alias - self._alias_dict[alias] = cmd.name - return cmd - def resolve_alias(self, cmd_name): if cmd_name in self._alias_dict.keys(): return self._alias_dict[cmd_name] diff --git a/profiler/advisor/utils/utils.py b/profiler/advisor/utils/utils.py index 710084ef8c942bf1a3699cd7015b50c6d1676333..1094145b5abc1039be2038ca889aaebb24601db8 100644 --- a/profiler/advisor/utils/utils.py +++ b/profiler/advisor/utils/utils.py @@ -120,7 +120,8 @@ def singleton(cls): # 过滤出函数对象 function_objs = [ - member[1] for member in members + member[1] + for member in members if inspect.isfunction(member[1]) or inspect.ismethod(member[1]) ] for function_obj in function_objs: