[rocprofiler-compute] refactor bug fixes (#994)

This commit is contained in:
xuchen-amd
2025-09-16 14:20:33 -04:00
committed by GitHub
parent 05dc14934a
commit 288bca17ea
7 changed files with 37 additions and 29 deletions
@@ -147,7 +147,10 @@ class RocProfCompute_Base:
for file in result_files: for file in result_files:
Path(file).unlink() Path(file).unlink()
console_debug(f"Deleted file: {file}") console_debug(f"Deleted file: {file}")
return return None
# Collect files to process - normalize to Path objects
files: list[Path] = []
# Set default output directory if not specified # Set default output directory if not specified
if isinstance(args.path, str): if isinstance(args.path, str):
@@ -168,7 +171,7 @@ class RocProfCompute_Base:
f for f in files if not f.name.endswith("_marker_api_trace.csv") f for f in files if not f.name.endswith("_marker_api_trace.csv")
] ]
elif isinstance(args.path, list): elif isinstance(args.path, list):
files = args.path files = [Path(path) for path in args.path]
else: else:
console_error(f"Invalid workload directory. Cannot resolve {args.path}") console_error(f"Invalid workload directory. Cannot resolve {args.path}")
@@ -176,6 +179,11 @@ class RocProfCompute_Base:
df = None df = None
for i, file in enumerate(files): for i, file in enumerate(files):
current_df = pd.read_csv(file) current_df = pd.read_csv(file)
if current_df.empty:
console_warning("join_prof", f"Empty dataframe from {file}")
continue
if args.join_type == "kernel": if args.join_type == "kernel":
key = current_df.groupby("Kernel_Name").cumcount() key = current_df.groupby("Kernel_Name").cumcount()
current_df["key"] = current_df.Kernel_Name + " - " + key.astype(str) current_df["key"] = current_df.Kernel_Name + " - " + key.astype(str)
@@ -190,7 +198,8 @@ class RocProfCompute_Base:
) )
else: else:
console_error( console_error(
f"{args.join_type} is an unrecognized option for --join-type" "join_prof",
f"{args.join_type} is an unrecognized option for --join-type",
) )
if df is None: if df is None:
@@ -202,7 +211,8 @@ class RocProfCompute_Base:
) )
if df is None or df.empty: if df is None or df.empty:
return console_warning("join_prof", "No data available after processing all files")
return None
# TODO: check for any mismatch in joins # TODO: check for any mismatch in joins
duplicate_cols = { duplicate_cols = {
@@ -238,10 +248,11 @@ class RocProfCompute_Base:
current_df = df[cols] current_df = df[cols]
if not test_df_column_equality(current_df): if not test_df_column_equality(current_df):
console_warning( console_warning(
f"Detected differing {key} values while joining pmc_perf.csv" "join_prof",
f"Detected differing {key} values while joining pmc_perf.csv",
) )
else: else:
console_debug(f"Successfully joined {key} in pmc_perf.csv") console_debug("join_prof", f"Successfully joined {key} in pmc_perf.csv")
# now, we can: # now, we can:
#   A) throw away any of the "boring" duplicates #   A) throw away any of the "boring" duplicates
@@ -321,7 +332,8 @@ class RocProfCompute_Base:
df["End_Timestamp"] = mean_end df["End_Timestamp"] = mean_end
# finally, join the drop key # finally, join the drop key
df = df.drop(columns=["key"]) if "key" in df.columns:
df = df.drop(columns=["key"])
# save to file and delete old file(s) # save to file and delete old file(s)
# skip if we're being called outside of rocprof-compute # skip if we're being called outside of rocprof-compute
@@ -330,8 +342,8 @@ class RocProfCompute_Base:
if not args.verbose: if not args.verbose:
for file in files: for file in files:
# Do not remove accumulate counter files # Do not remove accumulate counter files
if "SQ_" not in file or "SQC_" not in file: if "SQ_" not in file.name or "SQC_" not in file.name:
Path(file).unlink() file.unlink()
return None return None
else: else:
return df return df
@@ -88,7 +88,7 @@ class tui_analysis(OmniAnalyze_Base):
# 1. load top kernel # 1. load top kernel
parser.load_non_mertrics_table( parser.load_non_mertrics_table(
workload=self._runs[self.path], dir=self.path, args=self.args workload=self._runs[self.path], dir_path=self.path, args=self.args
) )
# 2. Generate kernel-specific dataframes # 2. Generate kernel-specific dataframes
@@ -33,6 +33,3 @@ APP_TITLE = "ROCm Compute Profiler TUI"
# Widget configurations # Widget configurations
DEFAULT_COLLAPSIBLE_STATE = True # True = collapsed by default DEFAULT_COLLAPSIBLE_STATE = True # True = collapsed by default
# File paths
DEFAULT_START_PATH = None # None uses cwd
@@ -116,7 +116,7 @@ class RocprofTUIApp(App):
def on_recent_selected(self, selected_dir: Optional[str]) -> None: def on_recent_selected(self, selected_dir: Optional[str]) -> None:
if selected_dir: if selected_dir:
self.main_view.selected_path = selected_dir self.main_view.selected_path = Path(selected_dir)
self.main_view.run_analysis() self.main_view.run_analysis()
@on(Button.Pressed, "#menu-open-workload") @on(Button.Pressed, "#menu-open-workload")
@@ -4,28 +4,28 @@
# collapsed: true # collapsed: true
sections: sections:
- title: "High Level Analysis" - title: "High Level Analysis"
collapsed: true collapsed: True
class: "sysinfo-section" class: "sysinfo-section"
subsections: subsections:
- title: "GPU Speed-of-Light" - title: "GPU Speed-of-Light"
data_path: ["32. GPU Speed-of-Light", "32.1 GPU Speed-of-Light"] data_path: ["32. GPU Speed-of-Light", "32.1 GPU Speed-of-Light"]
collapsed: true collapsed: True
- title: "Compute Throughput" - title: "Compute Throughput"
data_path: ["33. Compute Throughput", "33.1 Compute Throughput"] data_path: ["33. Compute Throughput", "33.1 Compute Throughput"]
collapsed: true collapsed: True
- title: "Memory Throughput" - title: "Memory Throughput"
data_path: ["34. Memory Throughput", "34.1 Memory Throughput"] data_path: ["34. Memory Throughput", "34.1 Memory Throughput"]
collapsed: true collapsed: True
- title: "Memory Chart" - title: "Memory Chart"
data_path: ["3. Memory Chart", "3.1 Memory Chart"] data_path: ["3. Memory Chart", "3.1 Memory Chart"]
collapsed: true collapsed: True
tui_style: "mem_chart" tui_style: "mem_chart"
- title: "Detailed Block Analysis" - title: "Detailed Block Analysis"
collapsed: true collapsed: True
class: "block-section" class: "block-section"
subsections: subsections:
- arch_config_data: true - arch_config_data: True
exclude_keys: exclude_keys:
- "0. Top Stats" - "0. Top Stats"
- "1. System Info" - "1. System Info"
@@ -35,12 +35,12 @@ sections:
- "32. GPU Speed-of-Light" - "32. GPU Speed-of-Light"
- "33. Compute Throughput" - "33. Compute Throughput"
- "34. Memory Throughput" - "34. Memory Throughput"
collapsed: true collapsed: True
- title: "Source Level Analysis" - title: "Source Level Analysis"
collapsed: true collapsed: True
class: "source-section" class: "source-section"
subsections: subsections:
- title: "PC Sampling" - title: "PC Sampling"
data_path: ["21. PC Sampling", "21.1 PC Sampling"] data_path: ["21. PC Sampling", "21.1 PC Sampling"]
collapsed: true collapsed: True
@@ -38,7 +38,6 @@ from textual.reactive import reactive
from textual.widgets import DataTable from textual.widgets import DataTable
from rocprof_compute_tui.analysis_tui import tui_analysis from rocprof_compute_tui.analysis_tui import tui_analysis
from rocprof_compute_tui.config import DEFAULT_START_PATH
from rocprof_compute_tui.utils.tui_utils import Logger, LogLevel from rocprof_compute_tui.utils.tui_utils import Logger, LogLevel
from rocprof_compute_tui.widgets.center_panel.center_area import CenterPanel from rocprof_compute_tui.widgets.center_panel.center_area import CenterPanel
from rocprof_compute_tui.widgets.menu_bar.menu_bar import MenuBar from rocprof_compute_tui.widgets.menu_bar.menu_bar import MenuBar
@@ -56,7 +55,6 @@ class MainView(Horizontal):
def __init__(self) -> None: def __init__(self) -> None:
super().__init__(id="main-container") super().__init__(id="main-container")
self.start_path = Path(DEFAULT_START_PATH) if DEFAULT_START_PATH else Path.cwd()
self.logger = Logger() self.logger = Logger()
self.logger.info("MainView initialized", update_ui=False) self.logger.info("MainView initialized", update_ui=False)
@@ -138,7 +136,7 @@ class MainView(Horizontal):
analyzer.sanitize() analyzer.sanitize()
# 2. Load and process system info and Configure SoC # 2. Load and process system info and Configure SoC
sysinfo_path = Path(self.selected_path) / "sysinfo.csv" sysinfo_path = self.selected_path / "sysinfo.csv"
if not sysinfo_path.exists(): if not sysinfo_path.exists():
raise FileNotFoundError(f"sysinfo.csv not found at {sysinfo_path}") raise FileNotFoundError(f"sysinfo.csv not found at {sysinfo_path}")
@@ -20,8 +20,9 @@
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. # THE SOFTWARE.
############################################################################## ##############################################################################
from pathlib import Path
from typing import Any, Optional from typing import Any, Optional
from textual import on from textual import on
@@ -87,7 +88,7 @@ class MenuBar(Container):
def on_recent_selected(selected_dir: Optional[str]) -> None: def on_recent_selected(selected_dir: Optional[str]) -> None:
if selected_dir: if selected_dir:
self.parent_main_view.selected_path = selected_dir self.parent_main_view.selected_path = Path(selected_dir)
self.query_one("#file-dropdown", DropdownMenu).add_class("hidden") self.query_one("#file-dropdown", DropdownMenu).add_class("hidden")
self.parent_main_view.run_analysis() self.parent_main_view.run_analysis()