Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 42 additions & 4 deletions projects/rocprofiler-sdk/source/lib/python/rocpd/summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,8 +311,24 @@ def generate_domain_query(
return (view_name, domain_select)


def create_summary_queries(connection: RocpdImportData, by_rank=False):
"""Create summary queries for eligible temporary views in the database."""
def _view_matches_category(view_name: str, category: str) -> bool:
"""Return True if view name matches the category."""
v = view_name.lower()
c = category.lower()
plural_map = (c, f"{c}s")
return v in plural_map or any(v.startswith(f"{itr}_") for itr in plural_map)


def create_summary_queries(
connection: RocpdImportData,
by_rank=False,
only_view_categories=None,
):
"""Create summary queries for eligible temporary views in the database.

When only_view_categories is set (e.g. ["kernel"]), only include views whose
name matches one of the categories (e.g. "kernels" matches "kernel").
"""

NAME_COLUMN_MAP = {
"memory_allocations": "type",
Expand All @@ -330,6 +346,12 @@ def create_summary_queries(connection: RocpdImportData, by_rank=False):
if any(pattern in view_name for pattern in avoid_view_pattern):
continue

if only_view_categories is not None:
if not any(
_view_matches_category(view_name, cat) for cat in only_view_categories
):
continue

columns = get_temp_view_columns(connection, view_name)
if not required_columns.issubset(columns):
continue
Expand Down Expand Up @@ -477,8 +499,24 @@ def generate_all_summaries(connection: RocpdImportData, **kwargs: Any) -> None:

summary_queries = {}

# Create the summary queries
summary_queries.update(create_summary_queries(connection, by_rank))
# Create the summary queries.
# When region_categories is specified (and not NONE), only include view-based
# summaries that match those categories and only region summaries for those categories.
# With --region-categories NONE we only skip region summaries and still include
# all view-based summaries.
is_none_categories = (
region_categories is not None
and len(region_categories) == 1
and str(region_categories[0]).strip().upper() == "NONE"
)
if region_categories is None or is_none_categories:
summary_queries.update(create_summary_queries(connection, by_rank))
else:
summary_queries.update(
create_summary_queries(
connection, by_rank, only_view_categories=region_categories
)
)
summary_queries.update(
create_summary_region_queries(
connection, by_rank, region_categories=region_categories
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -516,3 +516,62 @@ def get_json_corr_id(x):

for a, b in zip(_csv_data_sorted, _js_data_sorted):
_perform_csv_json_match(a, b, keys_mapping[category], json_data)


def test_summary_region_category_filtering(
summary_dir, expected_categories=None, allow_none=False
):
"""
Test that summary output contains ONLY the expected categories.

Args:
summary_dir: Path to directory containing summary CSV files
expected_categories: List of category names that should be present (e.g., ['kernel', 'hip'])
allow_none: If True, allows no region summaries (for --region-categories NONE test)
"""
import os
import glob

if not os.path.exists(summary_dir):
raise FileNotFoundError(f"Summary directory not found: {summary_dir}")

# Get all CSV files
csv_files = glob.glob(os.path.join(summary_dir, "*.csv"))
basenames = [os.path.basename(f) for f in csv_files]

assert len(basenames) > 0, f"No summary files found in {summary_dir}"

print(f"\nFound {len(basenames)} summary files in {summary_dir}:")
for name in sorted(basenames):
print(f" - {name}")

# For NONE test: ensure no region-based summaries are generated
if allow_none:
# Region summaries have filenames like "rocm_hip_*.csv", "rocm_hsa_*.csv"
region_files = [f for f in basenames if f.lower().startswith("rocm_")]
assert len(region_files) == 0, (
f"--region-categories NONE should not generate region summaries, "
f"but found: {region_files}"
)

# Check that expected categories are present and ONLY those categories exist
if expected_categories:
# 1. Check all expected categories are present
for category in expected_categories:
category_lower = category.lower()
matching_files = [f for f in basenames if category_lower in f.lower()]
assert len(matching_files) > 0, (
f"Expected category '{category}' not found. "
f"No files matching '{category_lower}' in {basenames}"
)

# 2. Check no unexpected categories exist
for filename in basenames:
filename_lower = filename.lower()
matches_expected = any(
cat.lower() in filename_lower for cat in expected_categories
)
assert matches_expected, (
f"Unexpected file '{filename}' found. "
f"Does not match any expected category: {expected_categories}"
)
84 changes: 84 additions & 0 deletions projects/rocprofiler-sdk/tests/rocprofv3/rocpd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,72 @@ rocprofiler_add_integration_execute_test(
FIXTURES_REQUIRED rocprofv3-test-rocpd
DISABLED "${MULTIPROC_IS_DISABLED}")

#########################################################################################
#
# Region category filtering tests
#
#########################################################################################

# Test --region-categories with single category (KERNEL)
rocprofiler_add_integration_execute_test(
rocprofv3-test-rocpd-summary-region-category-kernel
COMMAND
${Python3_EXECUTABLE} -m rocpd summary --region-categories KERNEL -f csv -d
${CMAKE_CURRENT_BINARY_DIR}/rocpd-output-data/summary-kernel -i
${CMAKE_CURRENT_BINARY_DIR}/rocpd-input-data/out_results.db
DEPENDS rocprofiler-sdk::rocprofv3
TIMEOUT 45
LABELS "integration-tests;rocpd"
PRELOAD "${ROCPROFILER_MEMCHECK_PRELOAD_ENV_VALUE}"
ENVIRONMENT "${rocprofv3-rocpd-env}"
FIXTURES_SETUP rocprofv3-test-rocpd-region-category
FIXTURES_REQUIRED rocprofv3-test-rocpd)

# Test --region-categories with single category (HIP)
rocprofiler_add_integration_execute_test(
rocprofv3-test-rocpd-summary-region-category-hip
COMMAND
${Python3_EXECUTABLE} -m rocpd summary --region-categories HIP -f csv -d
${CMAKE_CURRENT_BINARY_DIR}/rocpd-output-data/summary-hip -i
${CMAKE_CURRENT_BINARY_DIR}/rocpd-input-data/out_results.db
DEPENDS rocprofiler-sdk::rocprofv3
TIMEOUT 45
LABELS "integration-tests;rocpd"
PRELOAD "${ROCPROFILER_MEMCHECK_PRELOAD_ENV_VALUE}"
ENVIRONMENT "${rocprofv3-rocpd-env}"
FIXTURES_SETUP rocprofv3-test-rocpd-region-category
FIXTURES_REQUIRED rocprofv3-test-rocpd)

# Test --region-categories with multiple categories
rocprofiler_add_integration_execute_test(
rocprofv3-test-rocpd-summary-region-category-multiple
COMMAND
${Python3_EXECUTABLE} -m rocpd summary --region-categories HIP KERNEL -f csv -d
${CMAKE_CURRENT_BINARY_DIR}/rocpd-output-data/summary-multiple -i
${CMAKE_CURRENT_BINARY_DIR}/rocpd-input-data/out_results.db
DEPENDS rocprofiler-sdk::rocprofv3
TIMEOUT 45
LABELS "integration-tests;rocpd"
PRELOAD "${ROCPROFILER_MEMCHECK_PRELOAD_ENV_VALUE}"
ENVIRONMENT "${rocprofv3-rocpd-env}"
FIXTURES_SETUP rocprofv3-test-rocpd-region-category
FIXTURES_REQUIRED rocprofv3-test-rocpd)

# Test --region-categories NONE (all views, no regions)
rocprofiler_add_integration_execute_test(
rocprofv3-test-rocpd-summary-region-category-none
COMMAND
${Python3_EXECUTABLE} -m rocpd summary --region-categories NONE -f csv -d
${CMAKE_CURRENT_BINARY_DIR}/rocpd-output-data/summary-none -i
${CMAKE_CURRENT_BINARY_DIR}/rocpd-input-data/out_results.db
DEPENDS rocprofiler-sdk::rocprofv3
TIMEOUT 45
LABELS "integration-tests;rocpd"
PRELOAD "${ROCPROFILER_MEMCHECK_PRELOAD_ENV_VALUE}"
ENVIRONMENT "${rocprofv3-rocpd-env}"
FIXTURES_SETUP rocprofv3-test-rocpd-region-category
FIXTURES_REQUIRED rocprofv3-test-rocpd)

#########################################################################################
#
# Validation
Expand Down Expand Up @@ -239,6 +305,24 @@ rocprofiler_add_integration_validate_test(
LABELS "integration-tests;rocpd"
FIXTURES_REQUIRED rocprofv3-test-rocpd-generation)

# Validate region category filtering
rocprofiler_add_integration_validate_test(
rocprofv3-test-rocpd-region-category-validation
TEST_PATHS validate_summary.py
COPY conftest.py
CONFIG pytest.ini
ARGS --summary-kernel-dir
${CMAKE_CURRENT_BINARY_DIR}/rocpd-output-data/summary-kernel
--summary-hip-dir
${CMAKE_CURRENT_BINARY_DIR}/rocpd-output-data/summary-hip
--summary-multiple-dir
${CMAKE_CURRENT_BINARY_DIR}/rocpd-output-data/summary-multiple
--summary-none-dir
${CMAKE_CURRENT_BINARY_DIR}/rocpd-output-data/summary-none
TIMEOUT 60
LABELS "integration-tests;rocpd;region-category"
FIXTURES_REQUIRED rocprofv3-test-rocpd-region-category)

#########################################################################################
#
# Package generation
Expand Down
41 changes: 41 additions & 0 deletions projects/rocprofiler-sdk/tests/rocprofv3/rocpd/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,26 @@ def pytest_addoption(parser):
action="store",
help="Path to summary markdown file.",
)
parser.addoption(
"--summary-kernel-dir",
action="store",
help="Path to KERNEL category summary output directory.",
)
parser.addoption(
"--summary-hip-dir",
action="store",
help="Path to HIP category summary output directory.",
)
parser.addoption(
"--summary-multiple-dir",
action="store",
help="Path to multiple categories summary output directory.",
)
parser.addoption(
"--summary-none-dir",
action="store",
help="Path to NONE category summary output directory.",
)

pd.set_option("display.width", 2000)
# increase debug display of pandas dataframes
Expand Down Expand Up @@ -161,3 +181,24 @@ def process_current_domain(_name, _list):
process_current_domain(current_name, current_list)

return domains


# Fixtures for region category summary tests
@pytest.fixture
def summary_kernel_dir(request):
return request.config.getoption("--summary-kernel-dir")


@pytest.fixture
def summary_hip_dir(request):
return request.config.getoption("--summary-hip-dir")


@pytest.fixture
def summary_multiple_dir(request):
return request.config.getoption("--summary-multiple-dir")


@pytest.fixture
def summary_none_dir(request):
return request.config.getoption("--summary-none-dir")
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/usr/bin/env python3

# MIT License
#
# Copyright (c) 2024-2025 Advanced Micro Devices, Inc. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# 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
# THE SOFTWARE.

import sys
import pytest


def test_summary_region_category_kernel(summary_kernel_dir):
"""Test that --region-categories KERNEL only produces kernel summaries."""
import rocprofiler_sdk.tests.rocprofv3 as rocprofv3

rocprofv3.test_summary_region_category_filtering(
summary_kernel_dir,
expected_categories=["kernel"],
)


def test_summary_region_category_hip(summary_hip_dir):
"""Test that --region-categories HIP only produces HIP summaries."""
import rocprofiler_sdk.tests.rocprofv3 as rocprofv3

rocprofv3.test_summary_region_category_filtering(
summary_hip_dir,
expected_categories=["hip"],
)


def test_summary_region_category_multiple(summary_multiple_dir):
"""Test that --region-categories HIP KERNEL produces those summaries."""
import rocprofiler_sdk.tests.rocprofv3 as rocprofv3

rocprofv3.test_summary_region_category_filtering(
summary_multiple_dir,
expected_categories=["hip", "kernel"],
)


def test_summary_region_category_none(summary_none_dir):
"""Test that --region-categories NONE includes views but no regions."""
import rocprofiler_sdk.tests.rocprofv3 as rocprofv3

rocprofv3.test_summary_region_category_filtering(
summary_none_dir,
expected_categories=["kernel", "memory"],
allow_none=True,
)


if __name__ == "__main__":
exit_code = pytest.main(["-x", __file__] + sys.argv[1:])
sys.exit(exit_code)
Loading