Analysis report block based filtering for profiling (#566)

* Analysis report block based filtering for profiling

* Profiling mode changes

- `-b` option now additionally accepts metric id(s), similar to `-b` option in analyze mode (e.g. 6, 6.2, 6.23)
    - Only counters mentioned in the selected analysis report blocks will be collected
        - Add parsing logic to identify hardware counters from analysis report blocks
        - Add filtering logic to only write filtered counters in perfmon files
        - Log not collected counters in one line
- `--list-metrics` option added in profile mode to list possible metric id(s) similar to analyze mode
- Write arguments provided during profiling in profiling_configuration.yaml file

* Analysis mode changes

- During analysis mode, only show report blocks selected during profiling
    - If `-b` option is provided in analysis mode, then follow provided filters
- Do not show empty tables in analysis report

* Miscellaneous changes

- Update CHANGELOG
- Add test cases
    - Instruction mix report block filter
    - Instruction mix and Memory chart report block filter
    - Instruction mix report block filter and CPC hardware block filter
    - TA hardware block filter
    - --list-metrics in profile mode should work
- Move binary handler fixtures to conftest.py to avoid importing
  fixtures
- cmake file in tests directory has been updated to compile sample/vmem.hip for testing

* Public documentation changes

- Use the term "Hardware report block" instead of "Hardware block"
- Add documentation for "--list-metrics" option in profile mode
- Add example of filtering by hardware report block such as instruction
  mix and wavefront launch statistics
- Add deprecation warning for hardware component (sq, tcc) based filtering
This commit is contained in:
vedithal-amd
2025-03-10 14:42:56 -04:00
کامیت شده توسط GitHub
والد 0aefd15b7b
کامیت 55cf0e237e
27فایلهای تغییر یافته به همراه748 افزوده شده و 199 حذف شده
+58 -7
مشاهده پرونده
@@ -29,7 +29,7 @@ import pandas as pd
from tabulate import tabulate
from utils import parser
from utils.utils import console_log, console_warning
from utils.utils import console_log, console_warning, convert_metric_id_to_panel_idx
hidden_columns = ["Tips", "coll_level"]
hidden_sections = [1900, 2000]
@@ -60,11 +60,20 @@ def get_table_string(df, transpose=False, decimal=2):
)
def show_all(args, runs, archConfigs, output):
def show_all(args, runs, archConfigs, output, profiling_config):
"""
Show all panels with their data in plain text mode.
"""
comparable_columns = parser.build_comparable_columns(args.time_unit)
filter_panel_ids = [
convert_metric_id_to_panel_idx(section)
for section in [
name
for name, type in profiling_config.get("filter_blocks", {}).items()
if type == "metric_id"
]
]
comparable_columns = parser.build_comparable_columns(args.time_unit)
for panel_id, panel in archConfigs.panel_configs.items():
# Skip panels that don't support baseline comparison
@@ -74,6 +83,27 @@ def show_all(args, runs, archConfigs, output):
for data_source in panel["data source"]:
for type, table_config in data_source.items():
# If block filtering was used during analysis, then dont use profiling config
# If block filtering was used in profiling config, only show those panels
# If block filtering not used in profiling config, show all panels
# Skip this table if table id or panel id is not present in block filters
# However, always show panel id <= 100
if (
not args.filter_metrics
and filter_panel_ids
and table_config["id"] not in filter_panel_ids
and panel_id not in filter_panel_ids
and panel_id > 100
):
table_id_str = (
str(table_config["id"] // 100)
+ "."
+ str(table_config["id"] % 100)
)
console_log(
f"Not showing table not selected during profiling: {table_id_str} {table_config['title']}"
)
continue
# take the 1st run as baseline
base_run, base_data = next(iter(runs.items()))
base_df = base_data.dfs[table_config["id"]]
@@ -207,7 +237,25 @@ def show_all(args, runs, archConfigs, output):
+ str(table_config["id"] % 100)
)
if "title" in table_config and table_config["title"]:
# Check if any column in df is empty
is_empty_columns_exist = any(
[
df.columns[col_idx]
for col_idx in range(len(df.columns))
if df.replace("", None).iloc[:, col_idx].isnull().all()
]
)
# Do not print the table if any column is empty
if is_empty_columns_exist:
console_log(
f"Not showing table with empty column(s): {table_id_str} {table_config['title']}"
)
if (
"title" in table_config
and table_config["title"]
and not is_empty_columns_exist
):
ss += table_id_str + " " + table_config["title"] + "\n"
if args.df_file_dir:
@@ -238,10 +286,13 @@ def show_all(args, runs, archConfigs, output):
and "columnwise" in table_config
and table_config["columnwise"] == True
)
ss += (
get_table_string(df, transpose=transpose, decimal=args.decimal)
+ "\n"
)
if not is_empty_columns_exist:
ss += (
get_table_string(
df, transpose=transpose, decimal=args.decimal
)
+ "\n"
)
if ss:
print("\n" + "-" * 80, file=output)