CLI: enable roofline plot (#760)

* enable roofline plot in cli.

* Add roofline to analysis config.

* Unify global variables.

* Disable roofline for baseline comparison and gfx908.

* Add check for roofline.csv

[ROCm/rocprofiler-compute commit: 80159ee117]
This commit is contained in:
xuchen-amd
2025-06-18 13:19:58 -04:00
کامیت شده توسط GitHub
والد ab985464ef
کامیت 0b6e03adb0
11فایلهای تغییر یافته به همراه73 افزوده شده و 21 حذف شده
@@ -6,6 +6,8 @@ Full documentation for ROCm Compute Profiler is available at [https://rocm.docs.
### Added
* Support Roofline plot on CLI (single run)
* Stochastic (hardware-based) PC sampling has been enabled for AMD Instinct MI300X series and later accelerators.
* Sorting of PC sampling by type: offset or count.
@@ -60,7 +62,7 @@ Full documentation for ROCm Compute Profiler is available at [https://rocm.docs.
* Add --rocprofiler-sdk-library-path runtime option to choose the path to rocprofiler-sdk library to be used
* Using rocprof v1 / v2 / v3 interfaces will trigger a deprecation warning to use rocprofiler-sdk interface
* Support MEM chart on CLI(single run)
* Support MEM chart on CLI (single run)
* Add deprecation warning for database update mode.
@@ -26,4 +26,7 @@ from pathlib import Path
# NB: Creating a new module to share global vars across modules
rocprof_compute_home = Path(__file__).resolve().parent
prog = "rocprofiler-compute"
PROJECT_NAME = "rocprofiler-compute"
HIDDEN_COLUMNS = ["Tips", "coll_level"]
HIDDEN_SECTIONS = [400, 1900, 2000]
@@ -79,6 +79,7 @@ class cli_analysis(OmniAnalyze_Base):
def run_analysis(self):
"""Run CLI analysis."""
super().run_analysis()
if self.get_args().list_stats:
tty.show_kernel_stats(
self.get_args(),
@@ -89,6 +90,26 @@ class cli_analysis(OmniAnalyze_Base):
self._output,
)
else:
roof_plot = None
# 1. check if not baseline && compatible soc:
if (len(self.get_args().path)) == 1 and self._runs[
self.get_args().path[0][0]
].sys_info.iloc[0]["gpu_arch"] in [
"gfx90a",
"gfx940",
"gfx941",
"gfx942",
"gfx950",
]:
# add roofline plot to cli output
roof_obj = self.get_socs()[
self._runs[self.get_args().path[0][0]].sys_info.iloc[0]["gpu_arch"]
].roofline_obj
if roof_obj:
# NOTE: using default data type
roof_plot = roof_obj.cli_generate_plot(roof_obj.get_dtype()[0])
tty.show_all(
self.get_args(),
self._runs,
@@ -97,4 +118,5 @@ class cli_analysis(OmniAnalyze_Base):
],
self._output,
self._profiling_config,
roof_plot=roof_plot,
)
@@ -32,13 +32,12 @@ import dash_bootstrap_components as dbc
from dash import dcc, html
from dash.dependencies import Input, Output, State
from config import HIDDEN_COLUMNS, PROJECT_NAME
from rocprof_compute_analyze.analysis_base import OmniAnalyze_Base
from utils import file_io, parser
from utils.gui import build_bar_chart, build_table_chart
from utils.logger import console_debug, console_error, demarcate
PROJECT_NAME = "rocprofiler-compute"
class webui_analysis(OmniAnalyze_Base):
def __init__(self, args, supported_archs):
@@ -50,7 +49,7 @@ class webui_analysis(OmniAnalyze_Base):
self.arch = None
self.__hidden_sections = ["Memory Chart", "Roofline"]
self.__hidden_columns = ["Tips", "coll_level"]
self.__hidden_columns = HIDDEN_COLUMNS
# define different types of bar charts
self.__barchart_elements = {
"instr_mix": [1001, 1002],
@@ -322,7 +322,7 @@ class RocProfCompute:
profiler.pre_processing()
console_debug('starting "run_profiling" and about to start rocprof\'s workload')
time_start_prof = time.time()
profiler.run_profiling(self.__version["ver"], config.prog)
profiler.run_profiling(self.__version["ver"], config.PROJECT_NAME)
time_end_prof = time.time()
console_debug(
'finished "run_profiling" and finished rocprof\'s workload, time taken was {} m {} sec'.format(
@@ -0,0 +1,8 @@
---
Panel Config:
id: 400
title: Roofline
data source:
- None:
id: 401
title: Roofline
@@ -2,7 +2,6 @@ import copy
import logging
import os
import re
import sys
from collections import defaultdict
from datetime import datetime
from enum import Enum
@@ -10,8 +9,7 @@ from pathlib import Path
import pandas as pd
HIDDEN_SECTIONS = [1900, 2000]
HIDDEN_COLUMNS = ["Tips", "coll_level"]
from config import HIDDEN_COLUMNS, HIDDEN_SECTIONS
supported_field = [
"Value",
@@ -573,7 +573,6 @@ class Roofline:
return fig
@demarcate
def cli_generate_plot(self, dtype):
"""
Plot CLI mode roofline analysis in terminal using plotext
@@ -609,8 +608,16 @@ class Roofline:
self.__run_parameters["mem_level"].remove("vL1D")
self.__run_parameters["mem_level"].append("L1")
roofline_csv = str(
Path(self.__run_parameters["workload_dir"][0][0]).joinpath("roofline.csv")
)
roofline_csv_exists = Path(roofline_csv).is_file()
if not roofline_csv_exists:
console_log("roofline", "{} does not exist".format(roofline_csv))
return
app_path = str(
Path(self.__run_parameters["workload_dir"]).joinpath("pmc_perf.csv")
Path(self.__run_parameters["workload_dir"][0][0]).joinpath("pmc_perf.csv")
)
roofline_exists = Path(app_path).is_file()
if not roofline_exists:
@@ -844,6 +851,9 @@ class Roofline:
if self.__run_parameters["is_standalone"]:
self.standalone_roofline()
def get_dtype(self):
return self.__run_parameters["roofline_data_type"]
def to_int(a):
if str(type(a)) == "<class 'NoneType'>":
@@ -25,10 +25,9 @@
from dash import html
from dash_svg import G, Path, Rect, Svg, Text
from config import HIDDEN_COLUMNS
from utils.logger import console_error
hidden_columns = ["Tips", "coll_level"]
def insert_chart_data(mem_data, base_data):
if len(mem_data) != 1:
@@ -591,7 +591,7 @@ def calc_ai(mspec, sort_type, ret_df):
def constuct_roof(roofline_parameters, dtype):
benchmark_results = str(
Path(roofline_parameters["workload_dir"]).joinpath("roofline.csv")
Path(roofline_parameters["workload_dir"][0][0]).joinpath("roofline.csv")
)
# -----------------------------------------------------
# Initialize roofline data dictionary from roofline.csv
@@ -28,13 +28,11 @@ from pathlib import Path
import pandas as pd
from tabulate import tabulate
from config import HIDDEN_COLUMNS, HIDDEN_SECTIONS
from utils import mem_chart, parser
from utils.logger import console_log, console_warning
from utils.utils import convert_metric_id_to_panel_idx
hidden_columns = ["Tips", "coll_level"]
hidden_sections = [1900, 2000]
def string_multiple_lines(source, width, max_rows):
"""
@@ -61,7 +59,7 @@ def get_table_string(df, transpose=False, decimal=2):
)
def show_all(args, runs, archConfigs, output, profiling_config):
def show_all(args, runs, archConfigs, output, profiling_config, roof_plot=None):
"""
Show all panels with their data in plain text mode.
"""
@@ -77,8 +75,12 @@ def show_all(args, runs, archConfigs, output, profiling_config):
comparable_columns = parser.build_comparable_columns(args.time_unit)
for panel_id, panel in archConfigs.panel_configs.items():
# show roofline
if panel_id == 400 and roof_plot:
show_roof_plot(roof_plot)
# Skip panels that don't support baseline comparison
if panel_id in hidden_sections:
if panel_id in HIDDEN_SECTIONS:
continue
ss = "" # store content of all data_source from one pannel
@@ -117,7 +119,7 @@ def show_all(args, runs, archConfigs, output, profiling_config):
or (args.cols and base_df.columns.get_loc(header) in args.cols)
or (type == "raw_csv_table")
):
if header in hidden_columns:
if header in HIDDEN_COLUMNS:
pass
elif header not in comparable_columns:
if (
@@ -149,7 +151,7 @@ def show_all(args, runs, archConfigs, output, profiling_config):
cur_df = data.dfs[table_config["id"]]
if (type == "raw_csv_table") or (
type == "metric_table"
and (not header in hidden_columns)
and (not header in HIDDEN_COLUMNS)
):
if run != base_run:
# calc percentage over the baseline
@@ -309,6 +311,7 @@ def show_all(args, runs, archConfigs, output, profiling_config):
.set_index("Metric")
.to_dict()["Value"],
)
ss += "\n"
else:
ss += (
get_table_string(
@@ -323,6 +326,14 @@ def show_all(args, runs, archConfigs, output, profiling_config):
print(ss, file=output)
def show_roof_plot(roof_plot):
# TODO: short term solution to display roofline plot
print("\n" + "-" * 80)
print("4. Roofline")
print("4.1 Roofline")
print(roof_plot)
def show_kernel_stats(args, runs, archConfigs, output):
"""
Show the kernels and dispatches from "Top Stats" section.