Unified configuration for metrics (#726)
* Show description of metrics during analysis
* Use --include-cols Description show the Description column in analyze mode (this is hidden by default)
* Remove tips field from analysis config
* Align metric names in analysis config and documentation
* Add unified config utils/unified_config.yaml
* Add python script utils/split_config.py to auto generate analysis configuration and documentation metrics description
* Add test case to ensure unified config is older than auto-generated config
* Auto generate analysis config and documentation metrics description
* Update CONTRIBUTING.md to add instructions to build documentation assets
* Add docker image and compose file to build documentation
* Update CHANGELOG and Documentation
* Use jinja template instead of hardcoding metric tables in documentation
[ROCm/rocprofiler-compute commit: bb44e90b2d]
This commit is contained in:
@@ -49,12 +49,16 @@ def filter_df(column, df, filt):
|
||||
|
||||
def multi_bar_chart(table_id, display_df):
|
||||
if table_id == 1604:
|
||||
nested_bar = {"NC": {}, "UC": {}, "RW": {}, "CC": {}}
|
||||
nested_bar = {}
|
||||
for index, row in display_df.iterrows():
|
||||
if not row["Coherency"] in nested_bar:
|
||||
nested_bar[row["Coherency"]] = {}
|
||||
nested_bar[row["Coherency"]][row["Xfer"]] = row["Avg"]
|
||||
if table_id == 1705: # L2 - Fabric Interface Stalls
|
||||
nested_bar = {"Read": {}, "Write": {}}
|
||||
nested_bar = {}
|
||||
for index, row in display_df.iterrows():
|
||||
if not row["Transaction"] in nested_bar:
|
||||
nested_bar[row["Transaction"]] = {}
|
||||
nested_bar[row["Transaction"]][row["Type"]] = row["Avg"]
|
||||
|
||||
return nested_bar
|
||||
@@ -307,14 +311,14 @@ def build_table_chart(
|
||||
else:
|
||||
formatted_columns.append(dict(id=col, name=col, type="text"))
|
||||
|
||||
# tooltip shows only on the 1st col for now if 'Tips' available
|
||||
# tooltip shows only on the 1st col for now if 'Metric Description' available
|
||||
table_tooltip = (
|
||||
[
|
||||
{
|
||||
column: {
|
||||
"value": (
|
||||
str(row["Tips"])
|
||||
if column == display_columns[0] and row["Tips"]
|
||||
str(row["Description"])
|
||||
if column == display_columns[0] and row["Description"]
|
||||
else ""
|
||||
),
|
||||
"type": "markdown",
|
||||
@@ -323,7 +327,7 @@ def build_table_chart(
|
||||
}
|
||||
for row in original_df.to_dict("records")
|
||||
]
|
||||
if "Tips" in original_df.columns.values.tolist()
|
||||
if "Description" in original_df.columns.values.tolist()
|
||||
else None
|
||||
)
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
from dash import html
|
||||
from dash_svg import G, Path, Rect, Svg, Text
|
||||
|
||||
from config import HIDDEN_COLUMNS
|
||||
from utils.logger import console_error
|
||||
|
||||
|
||||
@@ -312,7 +311,7 @@ def insert_chart_data(mem_data, base_data):
|
||||
id="sl1_rd",
|
||||
fill="#FFFFFF",
|
||||
fontSize="12px",
|
||||
children=format_value_for_display(memchart_values["VL1D Rd"]),
|
||||
children=memchart_values["sL1D Rd"],
|
||||
),
|
||||
Text(
|
||||
x="838",
|
||||
@@ -320,7 +319,7 @@ def insert_chart_data(mem_data, base_data):
|
||||
id="sl1_hit",
|
||||
fill="rgb(0, 0, 0)",
|
||||
fontSize="12px",
|
||||
children=memchart_values["VL1D Hit"],
|
||||
children=memchart_values["sL1D Hit"],
|
||||
),
|
||||
Text(
|
||||
x="838",
|
||||
@@ -328,7 +327,7 @@ def insert_chart_data(mem_data, base_data):
|
||||
id="sl1_lat",
|
||||
fill="rgb(0, 0, 0)",
|
||||
fontSize="12px",
|
||||
children=memchart_values["VL1D Lat"],
|
||||
children=memchart_values["sL1D Lat"],
|
||||
),
|
||||
Text(
|
||||
x="1000",
|
||||
@@ -336,7 +335,7 @@ def insert_chart_data(mem_data, base_data):
|
||||
id="sl1_l2_rd",
|
||||
fill="#FFFFFF",
|
||||
fontSize="12px",
|
||||
children=format_value_for_display(memchart_values["VL1D_L2 Rd"]),
|
||||
children=memchart_values["sL1D_L2 Rd"],
|
||||
),
|
||||
Text(
|
||||
x="1000",
|
||||
@@ -344,7 +343,7 @@ def insert_chart_data(mem_data, base_data):
|
||||
id="sl1_l2_wr",
|
||||
fill="#FFFFFF",
|
||||
fontSize="12px",
|
||||
children=format_value_for_display(memchart_values["VL1D_L2 Wr"]),
|
||||
children=memchart_values["sL1D_L2 Wr"],
|
||||
),
|
||||
Text(
|
||||
x="1008",
|
||||
@@ -352,7 +351,7 @@ def insert_chart_data(mem_data, base_data):
|
||||
id="sl1_l2_atom",
|
||||
fill="#FFFFFF",
|
||||
fontSize="12px",
|
||||
children=memchart_values["VL1D_L2 Atomic"],
|
||||
children=memchart_values["sL1D_L2 Atomic"],
|
||||
),
|
||||
# ----------------------------------------
|
||||
# Instr L1 Cache Block
|
||||
|
||||
@@ -1079,7 +1079,7 @@ class MemChart:
|
||||
wires_E_GLV.vl1_rd = metric_dict["VL1 Rd"]
|
||||
wires_E_GLV.vl1_wr = metric_dict["VL1 Wr"]
|
||||
wires_E_GLV.vl1_atomic = metric_dict["VL1 Atomic"]
|
||||
wires_E_GLV.sl1_rd = metric_dict["VL1D Rd"]
|
||||
wires_E_GLV.sl1_rd = metric_dict["sL1D Rd"]
|
||||
|
||||
wires_E_GLV.draw(canvas)
|
||||
|
||||
@@ -1146,8 +1146,8 @@ class MemChart:
|
||||
block_const_L1.y_max = block_vector_L1.y_min - 3
|
||||
block_const_L1.y_min = block_const_L1.y_max - 5
|
||||
|
||||
block_const_L1.hit = metric_dict["VL1D Hit"]
|
||||
block_const_L1.latency = metric_dict["VL1D Lat"]
|
||||
block_const_L1.hit = metric_dict["sL1D Hit"]
|
||||
block_const_L1.latency = metric_dict["sL1D Lat"]
|
||||
|
||||
block_const_L1.draw(canvas)
|
||||
|
||||
@@ -1174,9 +1174,9 @@ class MemChart:
|
||||
wires_L1_L2.vl1_l2_rd = metric_dict["VL1_L2 Rd"]
|
||||
wires_L1_L2.vl1_l2_wr = metric_dict["VL1_L2 Wr"]
|
||||
wires_L1_L2.vl1_l2_atomic = metric_dict["VL1_L2 Atomic"]
|
||||
wires_L1_L2.sl1_l2_rd = metric_dict["VL1D_L2 Rd"]
|
||||
wires_L1_L2.sl1_l2_wr = metric_dict["VL1D_L2 Wr"]
|
||||
wires_L1_L2.sl1_l2_atomic = metric_dict["VL1D_L2 Atomic"]
|
||||
wires_L1_L2.sl1_l2_rd = metric_dict["sL1D_L2 Rd"]
|
||||
wires_L1_L2.sl1_l2_wr = metric_dict["sL1D_L2 Wr"]
|
||||
wires_L1_L2.sl1_l2_atomic = metric_dict["sL1D_L2 Atomic"]
|
||||
wires_L1_L2.il1_l2_req = metric_dict["IL1_L2 Rd"]
|
||||
|
||||
wires_L1_L2.draw(canvas)
|
||||
@@ -1331,9 +1331,9 @@ if __name__ == "__main__":
|
||||
metric_dict["VL1 Coalesce"] = 27
|
||||
metric_dict["VL1 Stall"] = 28
|
||||
|
||||
metric_dict["VL1D Rd"] = 29
|
||||
metric_dict["VL1D Hit"] = 30
|
||||
metric_dict["VL1D Lat"] = 31
|
||||
metric_dict["sL1D Rd"] = 29
|
||||
metric_dict["sL1D Hit"] = 30
|
||||
metric_dict["sL1D Lat"] = 31
|
||||
|
||||
metric_dict["IL1 Fetch"] = 32
|
||||
metric_dict["IL1 Hit"] = 33
|
||||
@@ -1344,9 +1344,9 @@ if __name__ == "__main__":
|
||||
metric_dict["VL1_L2 Wr"] = 37
|
||||
metric_dict["VL1_L2 Atomic"] = 38
|
||||
|
||||
metric_dict["VL1D_L2 Rd"] = 39
|
||||
metric_dict["VL1D_L2 Wr"] = 40
|
||||
metric_dict["VL1D_L2 Atomic"] = 41
|
||||
metric_dict["sL1D_L2 Rd"] = 39
|
||||
metric_dict["sL1D_L2 Wr"] = 40
|
||||
metric_dict["sL1D_L2 Atomic"] = 41
|
||||
metric_dict["IL1_L2 Rd"] = 42
|
||||
|
||||
metric_dict["L2 Hit"] = 43
|
||||
|
||||
@@ -228,7 +228,7 @@ class MIGPUSpecs:
|
||||
gpu_arch_lower = gpu_arch_.lower()
|
||||
|
||||
# Handle gfx942 with chip_id mapping
|
||||
if gpu_arch_lower not in ("gfx906", "gfx908", "gfx90a"):
|
||||
if gpu_arch_lower not in ("gfx908", "gfx90a"):
|
||||
if chip_id_ and int(chip_id_) in cls._chip_id_dict:
|
||||
gpu_model = cls._chip_id_dict.get(int(chip_id_))
|
||||
else:
|
||||
@@ -283,7 +283,7 @@ class MIGPUSpecs:
|
||||
4. Default settings (last resort)
|
||||
"""
|
||||
# Constants for legacy GPUs that don't support compute partitions
|
||||
LEGACY_ARCHS = {"gfx906", "gfx908", "gfx90a"}
|
||||
LEGACY_ARCHS = {"gfx908", "gfx90a"}
|
||||
LEGACY_MODELS = {"mi50", "mi60", "mi100", "mi210", "mi250", "mi250x"}
|
||||
|
||||
# Normalize inputs to lowercase for consistent comparison
|
||||
|
||||
@@ -509,17 +509,19 @@ def build_dfs(archConfigs, filter_metrics, sys_info):
|
||||
headers.append(k)
|
||||
|
||||
for key, tile in data_config["header"].items():
|
||||
if key != "metric" and key != "tips" and key != "expr":
|
||||
if key != "metric" and key != "expr":
|
||||
headers.append(tile)
|
||||
else:
|
||||
headers.append(data_config["header"]["metric"])
|
||||
for key, tile in data_config["header"].items():
|
||||
if key != "tips":
|
||||
if key != "metric":
|
||||
headers.append(tile)
|
||||
|
||||
# do we always need one?
|
||||
headers.append("coll_level")
|
||||
if "tips" in data_config["header"].keys():
|
||||
headers.append(data_config["header"]["tips"])
|
||||
|
||||
# Only add Metrics Description column if it is defined in the panel
|
||||
if "metrics_description" in panel:
|
||||
headers.append("Description")
|
||||
|
||||
df = pd.DataFrame(columns=headers)
|
||||
|
||||
@@ -563,16 +565,12 @@ def build_dfs(archConfigs, filter_metrics, sys_info):
|
||||
for bk, bv in simple_box.items():
|
||||
values.append(bv[0] + v + bv[1])
|
||||
else:
|
||||
if (
|
||||
k != "tips"
|
||||
and k != "coll_level"
|
||||
and k != "alias"
|
||||
):
|
||||
if k != "coll_level" and k != "alias":
|
||||
values.append(v)
|
||||
|
||||
else:
|
||||
for k, v in entries.items():
|
||||
if k != "tips" and k != "coll_level" and k != "alias":
|
||||
if k != "coll_level" and k != "alias":
|
||||
values.append(v)
|
||||
eqn_content.append(v)
|
||||
|
||||
@@ -584,8 +582,11 @@ def build_dfs(archConfigs, filter_metrics, sys_info):
|
||||
else:
|
||||
values.append(schema.pmc_perf_file_prefix)
|
||||
|
||||
if "tips" in entries.keys():
|
||||
values.append(entries["tips"])
|
||||
if "metrics_description" in panel:
|
||||
if key in panel["metrics_description"]:
|
||||
values.append(panel["metrics_description"][key])
|
||||
else:
|
||||
values.append("")
|
||||
|
||||
# print(headers, values)
|
||||
# print(key, entries)
|
||||
@@ -1459,7 +1460,14 @@ def build_comparable_columns(time_unit):
|
||||
Build comparable columns/headers for display
|
||||
"""
|
||||
comparable_columns = schema.supported_field
|
||||
top_stat_base = ["Count", "Sum", "Mean", "Median", "Standard Deviation"]
|
||||
top_stat_base = [
|
||||
"Count",
|
||||
"Sum",
|
||||
"Mean",
|
||||
"Median",
|
||||
"Standard Deviation",
|
||||
"Description",
|
||||
]
|
||||
|
||||
for h in top_stat_base:
|
||||
comparable_columns.append(h + "(" + time_unit + ")")
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
##############################################################################el
|
||||
|
||||
import copy
|
||||
import textwrap
|
||||
from pathlib import Path
|
||||
|
||||
import pandas as pd
|
||||
@@ -51,8 +52,21 @@ def string_multiple_lines(source, width, max_rows):
|
||||
|
||||
|
||||
def get_table_string(df, transpose=False, decimal=2):
|
||||
"""
|
||||
Convert DataFrame to a formatted table string, wrapping specified columns.
|
||||
"""
|
||||
df_to_show = df.transpose() if transpose else df
|
||||
wrap_columns = ["Description"]
|
||||
wrap_width = 40
|
||||
for col in wrap_columns:
|
||||
if col in df_to_show.columns:
|
||||
df_to_show[col] = (
|
||||
df_to_show[col]
|
||||
.astype(str)
|
||||
.apply(lambda x: textwrap.fill(x, width=wrap_width))
|
||||
)
|
||||
return tabulate(
|
||||
df.transpose() if transpose else df,
|
||||
df_to_show,
|
||||
headers="keys",
|
||||
tablefmt="fancy_grid",
|
||||
floatfmt="." + str(decimal) + "f",
|
||||
@@ -118,6 +132,10 @@ def show_all(args, runs, archConfigs, output, profiling_config, roof_plot=None):
|
||||
int(convert_metric_id_to_panel_info(metric_id)[0])
|
||||
for metric_id in filter_panel_ids
|
||||
]
|
||||
if args.include_cols:
|
||||
hidden_cols = list(set(config.HIDDEN_COLUMNS_CLI) - set(args.include_cols))
|
||||
else:
|
||||
hidden_cols = config.HIDDEN_COLUMNS_CLI
|
||||
|
||||
for panel_id, panel in archConfigs.panel_configs.items():
|
||||
# Skip panels that don't support baseline comparison
|
||||
@@ -196,12 +214,14 @@ def show_all(args, runs, archConfigs, output, profiling_config, roof_plot=None):
|
||||
df = pd.DataFrame(index=base_df.index)
|
||||
|
||||
for header in list(base_df.keys()):
|
||||
# For raw csv table, columns cannot be filtered
|
||||
# If columns are filtered, then skip the headers not in filtered columns
|
||||
if (
|
||||
(not args.cols)
|
||||
or (args.cols and base_df.columns.get_loc(header) in args.cols)
|
||||
or (type == "raw_csv_table")
|
||||
type == "raw_csv_table"
|
||||
or not args.cols
|
||||
or base_df.columns.get_loc(header) in args.cols
|
||||
):
|
||||
if header in config.HIDDEN_COLUMNS:
|
||||
if header in hidden_cols:
|
||||
pass
|
||||
elif header not in comparable_columns:
|
||||
if (
|
||||
@@ -236,8 +256,7 @@ def show_all(args, runs, archConfigs, output, profiling_config, roof_plot=None):
|
||||
cur_df = convert_time_columns(cur_df, args.time_unit)
|
||||
|
||||
if (type == "raw_csv_table") or (
|
||||
type == "metric_table"
|
||||
and (not header in config.HIDDEN_COLUMNS)
|
||||
type == "metric_table" and (not header in hidden_cols)
|
||||
):
|
||||
if run != base_run:
|
||||
# calc percentage over the baseline
|
||||
|
||||
Reference in New Issue
Block a user