From a171e776e47a48e79ae2803bcfbe7e395816f044 Mon Sep 17 00:00:00 2001 From: colramos-amd Date: Fri, 19 Jan 2024 13:46:01 -0600 Subject: [PATCH] Update headers based on latest rocprofv2 output. Overwrite old headers. Signed-off-by: colramos-amd --- src/omniperf_base.py | 6 +- src/omniperf_profile/profiler_base.py | 61 +++++++++------------ src/omniperf_profile/profiler_rocprof_v1.py | 17 +----- src/omniperf_profile/profiler_rocprof_v2.py | 17 +----- src/utils/file_io.py | 16 +++--- src/utils/gui_components/header.py | 4 +- src/utils/parser.py | 32 +++++------ src/utils/roofline_calc.py | 4 +- src/utils/tty.py | 4 +- src/utils/utils.py | 25 ++++++++- 10 files changed, 83 insertions(+), 103 deletions(-) diff --git a/src/omniperf_base.py b/src/omniperf_base.py index 9c82fc9a13..c9a4756c7e 100644 --- a/src/omniperf_base.py +++ b/src/omniperf_base.py @@ -151,12 +151,12 @@ class Omniperf: # in case of analyze mode, we can explicitly specify an arch # rather than detect from rocminfo if sys_info.empty: - arch = sys_info.iloc[0]["gpu_soc"] - target = sys_info.iloc[0]["name"] - else: mspec = get_machine_specs(0) arch = mspec.arch target = mspec.GPU + else: + arch = sys_info.iloc[0]["gpu_soc"] + target = sys_info.iloc[0]["name"] # instantiate underlying SoC support class # in case of analyze mode, __soc can accommodate multiple archs diff --git a/src/omniperf_profile/profiler_base.py b/src/omniperf_profile/profiler_base.py index 9aea08b585..7e21ab5f63 100644 --- a/src/omniperf_profile/profiler_base.py +++ b/src/omniperf_profile/profiler_base.py @@ -83,7 +83,7 @@ class OmniProfiler_Base(): # joins disparate runs less dumbly than rocprof @demarcate - def join_prof(self, output_headers, out=None): + def join_prof(self, out=None): """Manually join separated rocprof runs """ # Set default output directory if not specified @@ -101,12 +101,12 @@ class OmniProfiler_Base(): for i, file in enumerate(files): _df = pd.read_csv(file) if type(self.__args.path) == str else file if self.__args.join_type == "kernel": - key = _df.groupby(output_headers["Kernel_Name"]).cumcount() - _df["key"] = _df.KernelName + " - " + key.astype(str) + key = _df.groupby("Kernel_Name").cumcount() + _df["key"] = _df.Kernel_Name + " - " + key.astype(str) elif self.__args.join_type == "grid": - key = _df.groupby([output_headers["Kernel_Name"], output_headers["Grid_Size"]]).cumcount() + key = _df.groupby(["Kernel_Name", "Grid_Size"]).cumcount() _df["key"] = ( - _df[output_headers["Kernel_Name"]] + " - " + _df[output_headers["Grid_Size"]].astype(str) + " - " + key.astype(str) + _df["Kernel_Name"] + " - " + _df["Grid_Size"].astype(str) + " - " + key.astype(str) ) else: print("ERROR: Unrecognized --join-type") @@ -120,20 +120,20 @@ class OmniProfiler_Base(): # TODO: check for any mismatch in joins duplicate_cols = { - output_headers["GPU_ID"]: [col for col in df.columns if output_headers["GPU_ID"] in col], - output_headers["Grid_Size"]: [col for col in df.columns if output_headers["Grid_Size"] in col], - output_headers["Workgroup_Size"]: [col for col in df.columns if output_headers["Workgroup_Size"] in col], - output_headers["LDS_Per_Workgroup"]: [col for col in df.columns if output_headers["LDS_Per_Workgroup"] in col], - output_headers["Scratch_Per_Workitem"]: [col for col in df.columns if output_headers["Scratch_Per_Workitem"] in col], - output_headers["SGPR"]: [col for col in df.columns if output_headers["SGPR"] in col], + "GPU_ID": [col for col in df.columns if "GPU_ID" in col], + "Grid_Size": [col for col in df.columns if "Grid_Size" in col], + "Workgroup_Size": [col for col in df.columns if "Workgroup_Size" in col], + "LDS_Per_Workgroup": [col for col in df.columns if "LDS_Per_Workgroup" in col], + "Scratch_Per_Workitem": [col for col in df.columns if "Scratch_Per_Workitem" in col], + "SGPR": [col for col in df.columns if "SGPR" in col], } # Check for vgpr counter in ROCm < 5.3 if "vgpr" in df.columns: duplicate_cols["vgpr"] = [col for col in df.columns if "vgpr" in col] # Check for vgpr counter in ROCm >= 5.3 else: - duplicate_cols[output_headers["Arch_VGPR"]] = [col for col in df.columns if output_headers["Arch_VGPR"] in col] - duplicate_cols[output_headers["Accum_VGPR"]] = [col for col in df.columns if output_headers["Accum_VGPR"] in col] + duplicate_cols["Arch_VGPR"] = [col for col in df.columns if "Arch_VGPR" in col] + duplicate_cols["Accum_VGPR"] = [col for col in df.columns if "Accum_VGPR" in col] for key, cols in duplicate_cols.items(): _df = df[cols] if not test_df_column_equality(_df): @@ -158,23 +158,7 @@ class OmniProfiler_Base(): if not any( check in k for check in [ - # rocprofv1 headers - "gpu-id_", - "grd_", - "wgr_", - "lds_", - "scr_", - "vgpr_", - "sgpr_", - "Index_", - "queue-id", - "queue-index", - "pid", - "tid", - "fbar", - "sig", - "obj", - # rocprofv2 headers + # rocprofv2 headers "GPU_ID_", "Grid_Size_", "Workgroup_Size_", @@ -193,6 +177,13 @@ class OmniProfiler_Base(): "OBJ", # rocscope specific merged counters, keep original "dispatch_", + # extras + "sig", + "queue-id", + "queue-index", + "pid", + "tid", + "fbar", ] ) ] @@ -214,7 +205,7 @@ class OmniProfiler_Base(): ] ] #   C) sanity check the name and key - namekeys = [k for k in df.keys() if output_headers["Kernel_Name"] in k] + namekeys = [k for k in df.keys() if "Kernel_Name" in k] assert len(namekeys) for k in namekeys[1:]: assert (df[namekeys[0]] == df[k]).all() @@ -223,9 +214,9 @@ class OmniProfiler_Base(): bkeys = [] ekeys = [] for k in df.keys(): - if output_headers["Start_Timestamp"] in k: + if "Start_Timestamp" in k: bkeys.append(k) - if output_headers["End_Timestamp"] in k: + if "End_Timestamp" in k: ekeys.append(k) # compute mean begin and end timestamps endNs = df[ekeys].mean(axis=1) @@ -233,8 +224,8 @@ class OmniProfiler_Base(): # and replace df = df.drop(columns=bkeys) df = df.drop(columns=ekeys) - df["BeginNs"] = beginNs - df["EndNs"] = endNs + df["Start_Timestamp"] = beginNs + df["End_Timestamp"] = endNs # finally, join the drop key df = df.drop(columns=["key"]) # save to file and delete old file(s), skip if we're being called outside of Omniperf diff --git a/src/omniperf_profile/profiler_rocprof_v1.py b/src/omniperf_profile/profiler_rocprof_v1.py index 1cbe0888ba..4586f0d2ee 100644 --- a/src/omniperf_profile/profiler_rocprof_v1.py +++ b/src/omniperf_profile/profiler_rocprof_v1.py @@ -78,24 +78,9 @@ class rocprof_v1_profiler(OmniProfiler_Base): """ super().post_processing() - # Different rocprof versions have different headers. Set mapping for profiler output - output_headers = { - "Kernel_Name": "KernelName", - "Grid_Size": "grd", - "GPU_ID": "gpu", - "Workgroup_Size": "wgr", - "LDS_Per_Workgroup": "lds", - "Scratch_Per_Workitem": "scr", - "SGPR": "sgpr", - "Arch_VGPR": "arch_vgpr", - "Accum_VGPR": "accum_vgpr", - "Start_Timestamp": "BeginNs", - "End_Timestamp": "EndNs", - } - if self.ready_to_profile: # Manually join each pmc_perf*.csv output - self.join_prof(output_headers) + self.join_prof() # Replace timestamp data to solve a known rocprof bug replace_timestamps(self.get_args().path) # Demangle and overwrite original KernelNames diff --git a/src/omniperf_profile/profiler_rocprof_v2.py b/src/omniperf_profile/profiler_rocprof_v2.py index b7af178a8f..eb3d11fcd5 100644 --- a/src/omniperf_profile/profiler_rocprof_v2.py +++ b/src/omniperf_profile/profiler_rocprof_v2.py @@ -74,24 +74,9 @@ class rocprof_v2_profiler(OmniProfiler_Base): """ super().post_processing() - # Different rocprof versions have different headers. Set mapping for profiler output - output_headers = { - "Kernel_Name": "Kernel_Name", - "Grid_Size": "Grid_Size", - "GPU_ID": "GPU_ID", - "Workgroup_Size": "Workgroup_Size", - "LDS_Per_Workgroup": "LDS_Per_Workgroup", - "Scratch_Per_Workitem": "Scratch_Per_Workitem", - "SGPR": "SGPR", - "Arch_VGPR": "Arch_VGPR", - "Accum_VGPR": "Accum_VGPR", - "Start_Timestamp": "Start_Timestamp", - "End_Timestamp": "End_Timestamp", - } - if self.ready_to_profile: # Pass headers to join on - self.join_prof(output_headers) + self.join_prof() # Demangle and overwrite original KernelNames kernel_name_shortener(self.get_args().path, self.get_args().kernel_verbose) diff --git a/src/utils/file_io.py b/src/utils/file_io.py index 3c889738e5..0c50911112 100644 --- a/src/utils/file_io.py +++ b/src/utils/file_io.py @@ -95,28 +95,28 @@ def create_df_kernel_top_stats( # The logic below for filters are the same as in parser.apply_filters(), # which can be merged together if need it. if filter_gpu_ids: - df = df.loc[df["gpu-id"].astype(str).isin([filter_gpu_ids])] + df = df.loc[df["GPU_ID"].astype(str).isin([filter_gpu_ids])] if filter_dispatch_ids: # NB: support ignoring the 1st n dispatched execution by '> n' # The better way may be parsing python slice string if ">" in filter_dispatch_ids[0]: m = re.match("\> (\d+)", filter_dispatch_ids[0]) - df = df[df["Index"] > int(m.group(1))] + df = df[df["Dispatch_ID"] > int(m.group(1))] else: - df = df.loc[df["Index"].astype(str).isin(filter_dispatch_ids)] + df = df.loc[df["Dispatch_ID"].astype(str).isin(filter_dispatch_ids)] # First, create a dispatches file used to populate global vars - dispatch_info = df.loc[:, ["Index", "KernelName", "gpu-id"]] + dispatch_info = df.loc[:, ["Dispatch_ID", "Kernel_Name", "GPU_ID"]] dispatch_info.to_csv(os.path.join(raw_data_dir, "pmc_dispatch_info.csv"), index=False) time_stats = pd.concat( - [df["KernelName"], (df["EndNs"] - df["BeginNs"])], - keys=["KernelName", "ExeTime"], + [df["Kernel_Name"], (df["End_Timestamp"] - df["Start_Timestamp"])], + keys=["Kernel_Name", "ExeTime"], axis=1, ) - grouped = time_stats.groupby(by=["KernelName"]).agg( + grouped = time_stats.groupby(by=["Kernel_Name"]).agg( {"ExeTime": ["count", "sum", "mean", "median"]} ) @@ -147,7 +147,7 @@ def create_df_kernel_top_stats( grouped.to_csv(os.path.join(raw_data_dir, "pmc_kernel_top.csv"), index=False) elif sortby == "kernel": - grouped = grouped.sort_values("KernelName") + grouped = grouped.sort_values("Kernel_Name") grouped = grouped.head(max_kernel_num) # Display only the top n results grouped.to_csv(os.path.join(raw_data_dir, "pmc_kernel_top.csv"), index=False) diff --git a/src/utils/gui_components/header.py b/src/utils/gui_components/header.py index 7a62a4d616..a0f0193570 100644 --- a/src/utils/gui_components/header.py +++ b/src/utils/gui_components/header.py @@ -186,7 +186,7 @@ def get_header(raw_pmc, input_filters, kernel_names): str, raw_pmc[ schema.pmc_perf_file_prefix - ]["gpu-id"], + ]["GPU_ID"], ) ), True, @@ -219,7 +219,7 @@ def get_header(raw_pmc, input_filters, kernel_names): str, raw_pmc[ schema.pmc_perf_file_prefix - ]["Index"], + ]["Dispatch_ID"], ) ), id="disp-filt", diff --git a/src/utils/parser.py b/src/utils/parser.py index e4f31239d0..c4f01dca59 100644 --- a/src/utils/parser.py +++ b/src/utils/parser.py @@ -61,7 +61,7 @@ pmc_kernel_top_table_id = 1 # }, # { # "case": { "$eq": [ $normUnit, "per Sec"]} , -# "then": {"$divide":[{"$subtract": ["&EndNs", "&BeginNs" ]}, 1000000000]} +# "then": {"$divide":[{"$subtract": ["&End_Timestamp", "&Start_Timestamp" ]}, 1000000000]} # } # ], # "default": 1 @@ -70,7 +70,7 @@ pmc_kernel_top_table_id = 1 supported_denom = { "per_wave": "SQ_WAVES", "per_cycle": "GRBM_GUI_ACTIVE", - "per_second": "((EndNs - BeginNs) / 1000000000)", + "per_second": "((End_Timestamp - Start_Timestamp) / 1000000000)", "per_kernel": "1", } @@ -79,7 +79,7 @@ build_in_vars = { "numActiveCUs": "TO_INT(MIN((((ROUND(AVG(((4 * SQ_BUSY_CU_CYCLES) / GRBM_GUI_ACTIVE)), \ 0) / $maxWavesPerCU) * 8) + MIN(MOD(ROUND(AVG(((4 * SQ_BUSY_CU_CYCLES) \ / GRBM_GUI_ACTIVE)), 0), $maxWavesPerCU), 8)), $numCU))", - "kernelBusyCycles": "ROUND(AVG((((EndNs - BeginNs) / 1000) * $sclk)), 0)", + "kernelBusyCycles": "ROUND(AVG((((End_Timestamp - Start_Timestamp) / 1000) * $sclk)), 0)", } supported_call = { @@ -357,15 +357,15 @@ def gen_counter_list(formula): } built_in_counter = [ - "lds", - "grd", - "wgr", - "arch_vgpr", - "accum_vgpr", - "sgpr", - "scr", - "BeginNs", - "EndNs", + "LDS_Per_Workgroup", + "Grid_Size", + "Workgroup_Size", + "Arch_VGPR", + "Accum_VGPR", + "SGPR", + "Scratch_Per_Workitem", + "Start_Timestamp", + "End_Timestamp", ] visited = False @@ -492,7 +492,7 @@ def build_dfs(archConfigs, filter_metrics, sys_info): for data_source in panel["data source"]: for type, data_config in data_source.items(): if type == "metric_table": - headers = ["Index"] + headers = ["Dispatch_ID"] if ( "cli_style" in data_config @@ -600,7 +600,7 @@ def build_dfs(archConfigs, filter_metrics, sys_info): i += 1 - df.set_index("Index", inplace=True) + df.set_index("Dispatch_ID", inplace=True) # df.set_index('Metric', inplace=True) # print(tabulate(df, headers='keys', tablefmt='fancy_grid')) elif type == "raw_csv_table": @@ -828,7 +828,7 @@ def apply_filters(workload, dir, is_gui, debug): if workload.filter_gpu_ids: ret_df = ret_df.loc[ - ret_df[schema.pmc_perf_file_prefix]["gpu-id"] + ret_df[schema.pmc_perf_file_prefix]["GPU_ID"] .astype(str) .isin([workload.filter_gpu_ids]) ] @@ -890,7 +890,7 @@ def apply_filters(workload, dir, is_gui, debug): if ">" in workload.filter_dispatch_ids[0]: m = re.match("\> (\d+)", workload.filter_dispatch_ids[0]) ret_df = ret_df[ - ret_df[schema.pmc_perf_file_prefix]["Index"] > int(m.group(1)) + ret_df[schema.pmc_perf_file_prefix]["Dispatch_ID"] > int(m.group(1)) ] else: dispatches = [int(x) for x in workload.filter_dispatch_ids] diff --git a/src/utils/roofline_calc.py b/src/utils/roofline_calc.py index 9f1821a4de..6873d3a9c8 100644 --- a/src/utils/roofline_calc.py +++ b/src/utils/roofline_calc.py @@ -338,8 +338,8 @@ def calc_ai(sort_type, ret_df): logging.debug("[roofline] {}: Skipped hbm_data at index {}".format(kernelName[:35], idx)) pass - totalDuration += df["EndNs"][idx] - df["BeginNs"][idx] - avgDuration += df["EndNs"][idx] - df["BeginNs"][idx] + totalDuration += df["End_Timestamp"][idx] - df["Start_Timestamp"][idx] + avgDuration += df["End_Timestamp"][idx] - df["Start_Timestamp"][idx] calls += 1 diff --git a/src/utils/tty.py b/src/utils/tty.py index e8292bc394..95d6f976e7 100644 --- a/src/utils/tty.py +++ b/src/utils/tty.py @@ -82,10 +82,10 @@ def show_all(args, runs, archConfigs, output): if ( type == "raw_csv_table" and table_config["source"] == "pmc_kernel_top.csv" - and (header == "KernelName" or header == "Kernel_Name") + and header == "Kernel_Name" ): # NB: the width of kernel name might depend on the header of the table. - adjusted_name = base_df["KernelName"].apply( + adjusted_name = base_df["Kernel_Name"].apply( lambda x: string_multiple_lines(x, 40, 3) ) df = pd.concat([df, adjusted_name], axis=1) diff --git a/src/utils/utils.py b/src/utils/utils.py index 0d3dc07db2..9faf92e1d4 100644 --- a/src/utils/utils.py +++ b/src/utils/utils.py @@ -242,20 +242,39 @@ def run_prof(fname, profiler_options, target, workload_dir): ) # Remove temp directory shutil.rmtree(workload_dir + "/" + "out") + + # Overwrite headers + output_headers = { + "KernelName": "Kernel_Name", + "Index": "Dispatch_ID", + "grd": "Grid_Size", + "gpu-id": "GPU_ID", + "wgr": "Workgroup_Size", + "lds": "LDS_Per_Workgroup", + "scr": "Scratch_Per_Workitem", + "sgpr": "SGPR", + "arch_vgpr": "Arch_VGPR", + "accum_vgpr": "Accum_VGPR", + "BeginNs": "Start_Timestamp", + "EndNs": "End_Timestamp", + } + df = pd.read_csv(workload_dir + "/" + fbase + ".csv") + df.rename(columns=output_headers, inplace=True) + df.to_csv(workload_dir + "/" + fbase + ".csv", index=False) # write rocprof output to logging logging.info(output) def replace_timestamps(workload_dir): df_stamps = pd.read_csv(workload_dir + "/timestamps.csv") - if "BeginNs" in df_stamps.columns and "EndNs" in df_stamps.columns: + if "Start_Timestamp" in df_stamps.columns and "End_Timestamp" in df_stamps.columns: # Update timestamps for all *.csv output files for fname in glob.glob(workload_dir + "/" + "*.csv"): if path(fname).name != "sysinfo.csv": df_pmc_perf = pd.read_csv(fname) - df_pmc_perf["BeginNs"] = df_stamps["BeginNs"] - df_pmc_perf["EndNs"] = df_stamps["EndNs"] + df_pmc_perf["Start_Timestamp"] = df_stamps["Start_Timestamp"] + df_pmc_perf["End_Timestamp"] = df_stamps["End_Timestamp"] df_pmc_perf.to_csv(fname, index=False) else: warning = "WARNING: Incomplete profiling data detected. Unable to update timestamps."