From 553a5b7d3784eff894465002c4cd25ac2e213eac Mon Sep 17 00:00:00 2001 From: Meng Cao Date: Fri, 6 Mar 2026 21:28:01 -0600 Subject: [PATCH 1/9] add event id in rocpd to perfetto conversion --- .../lib/python/rocpd/source/perfetto.cpp | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/projects/rocprofiler-sdk/source/lib/python/rocpd/source/perfetto.cpp b/projects/rocprofiler-sdk/source/lib/python/rocpd/source/perfetto.cpp index 9f5008006fc..1dc41dd3a87 100644 --- a/projects/rocprofiler-sdk/source/lib/python/rocpd/source/perfetto.cpp +++ b/projects/rocprofiler-sdk/source/lib/python/rocpd/source/perfetto.cpp @@ -271,6 +271,30 @@ write_perfetto( return &pmc_info.at(pmc_id); }; + auto read_region_args = [&conn, &process, &ocfg](uint64_t region_id) { + if(!ocfg.annotate_args) return std::vector{}; + + return rocpd::read_sql_query( + conn, + fmt::format("SELECT * FROM region_args WHERE guid='{}' AND id={}", + process.guid, + region_id)); + }; + + auto is_hip_event_api = [](std::string_view opname) { + return (opname.rfind("hipEvent", 0) == 0) || (opname == "hipStreamWaitEvent"); + }; + + auto is_event_create_api = [](std::string_view opname) { + return opname.rfind("hipEventCreate", 0) == 0; + }; + + auto is_hip_event_handle_arg = [](std::string_view argname) { + // - "event" for hipEventRecord/hipEventSynchronize/hipStreamWaitEvent + // - "start"/"stop" for hipEventElapsedTime + return (argname == "event") || (argname == "start") || (argname == "stop"); + }; + { for(auto ditr : memory_copy_gen) for(const auto& itr : memory_copy_gen.get(ditr)) @@ -437,6 +461,11 @@ write_perfetto( auto _pmc_events = read_pmc_events(itr.event_id); auto _event = (ocfg.annotate_kfd) ? read_event(itr.event_id) : types::event{}; + auto _canon = std::string_view{itr.name}; + auto want_event_handle_annotations = + ocfg.annotate_args && is_hip_event_api(_canon) && !is_event_create_api(_canon); + auto _args = want_event_handle_annotations ? read_region_args(itr.id) + : std::vector{}; auto _category = ::perfetto::DynamicCategory{get_category_string(itr.category)}; TRACE_EVENT_BEGIN( @@ -497,6 +526,17 @@ write_perfetto( _extdata.kfd.value().record); } } + + if(want_event_handle_annotations) + { + for(const auto& a : _args) + { + if(is_hip_event_handle_arg(a.name)) + { + rocprofiler::sdk::add_perfetto_annotation(ctx, a.name, a.value); + } + } + } }); TRACE_EVENT_END(_category, track, itr.end); From 3b5ae5c86b3fa20bf4062f8701e0b52e7720669c Mon Sep 17 00:00:00 2001 From: Meng Cao Date: Fri, 6 Mar 2026 22:21:22 -0600 Subject: [PATCH 2/9] run clang-format --- .../source/lib/python/rocpd/source/perfetto.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/projects/rocprofiler-sdk/source/lib/python/rocpd/source/perfetto.cpp b/projects/rocprofiler-sdk/source/lib/python/rocpd/source/perfetto.cpp index 1dc41dd3a87..548f7cffa8a 100644 --- a/projects/rocprofiler-sdk/source/lib/python/rocpd/source/perfetto.cpp +++ b/projects/rocprofiler-sdk/source/lib/python/rocpd/source/perfetto.cpp @@ -276,9 +276,8 @@ write_perfetto( return rocpd::read_sql_query( conn, - fmt::format("SELECT * FROM region_args WHERE guid='{}' AND id={}", - process.guid, - region_id)); + fmt::format( + "SELECT * FROM region_args WHERE guid='{}' AND id={}", process.guid, region_id)); }; auto is_hip_event_api = [](std::string_view opname) { @@ -465,7 +464,7 @@ write_perfetto( auto want_event_handle_annotations = ocfg.annotate_args && is_hip_event_api(_canon) && !is_event_create_api(_canon); auto _args = want_event_handle_annotations ? read_region_args(itr.id) - : std::vector{}; + : std::vector{}; auto _category = ::perfetto::DynamicCategory{get_category_string(itr.category)}; TRACE_EVENT_BEGIN( From 478008b929701786c4852be3955108e103f438ec Mon Sep 17 00:00:00 2001 From: Meng Cao Date: Tue, 10 Mar 2026 17:40:16 -0500 Subject: [PATCH 3/9] enable tests for HIP event API argument annotations --- .../tests/pytest-packages/tests/rocprofv3.py | 90 +++++++++++++++++++ .../tests/rocprofv3/rocpd/CMakeLists.txt | 2 +- .../tests/rocprofv3/rocpd/validate.py | 7 ++ 3 files changed, 98 insertions(+), 1 deletion(-) diff --git a/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py b/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py index e7113abbf49..3f46d27baaf 100644 --- a/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py +++ b/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py @@ -516,3 +516,93 @@ 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_perfetto_hip_event_annotations(pftrace_data, pftrace_filename): + """ + Test that HIP event API calls have event handle annotations in perfetto. + This validates the feature that adds event ID annotations for HIP event API arguments. + + The feature adds annotations for: + - hipEventRecord: 'event' argument + - hipEventSynchronize: 'event' argument + - hipEventElapsedTime: 'start' and 'stop' arguments + - hipStreamWaitEvent: 'event' argument + + Args: + pftrace_data: DataFrame with perfetto trace data + pftrace_filename: Path to the perfetto trace file for direct queries + """ + import pytest + from rocprofiler_sdk.pytest_utils.perfetto_reader import PerfettoReader + + # Filter for HIP API traces + hip_api_data = pftrace_data.loc[pftrace_data["category"] == "hip_api"] + + if hip_api_data.empty: + pytest.skip("No HIP API traces found") + + # Get the PerfettoReader to query the args table + reader = PerfettoReader(pftrace_filename) + + # Access the trace processor directly + if not reader.trace_processor: + pytest.skip("Trace processor not available") + + # Query for HIP event API slices and their arguments + # The args table joins with slice table on arg_set_id + query = """ + SELECT + slice.name as slice_name, + slice.id as slice_id, + args.key as arg_name, + args.string_value as arg_value + FROM slice + JOIN args ON slice.arg_set_id = args.arg_set_id + WHERE slice.category = 'hip_api' + AND ( + slice.name LIKE '%hipEventRecord%' OR + slice.name LIKE '%hipEventSynchronize%' OR + slice.name LIKE '%hipEventElapsedTime%' OR + slice.name LIKE '%hipStreamWaitEvent%' + ) + AND ( + args.key = 'debug.event' OR + args.key = 'debug.start' OR + args.key = 'debug.stop' + ) + """ + + result = reader.query_tp(query) + + # Check if we found any event handle annotations + if result.empty: + pytest.skip( + "No HIP event API calls with event annotations found. " + ) + + print(f"\n{len(result)} HIP event argument annotations found:") + print(result.to_string()) + + # Validate the structure + assert "slice_name" in result.columns + assert "arg_name" in result.columns + assert "arg_value" in result.columns + + # Validate that we have expected argument names + found_arg_names = set(result["arg_name"].unique()) + expected_arg_names = {"debug.event", "debug.start", "debug.stop"} + assert found_arg_names.issubset( + expected_arg_names + ), f"Found unexpected arg names: {found_arg_names - expected_arg_names}" + + # Validate that event values are present (non-null) + null_values = result[result["arg_value"].isna()] + assert ( + null_values.empty + ), f"Found {len(null_values)} event arguments with null values" + + print( + f"\nValidation passed: Found {len(result)} event handle annotations " + f"with arg names: {found_arg_names}" + ) diff --git a/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/CMakeLists.txt b/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/CMakeLists.txt index ef10bb7720f..56f9282e64f 100644 --- a/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/CMakeLists.txt +++ b/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/CMakeLists.txt @@ -126,7 +126,7 @@ rocprofiler_add_integration_execute_test( rocprofiler_add_integration_execute_test( rocprofv3-test-rocpd-perfetto-generation COMMAND - ${Python3_EXECUTABLE} -m rocpd convert -f pftrace --kernel-rename -d + ${Python3_EXECUTABLE} -m rocpd convert -f pftrace --kernel-rename --annotate-args -d ${CMAKE_CURRENT_BINARY_DIR}/rocpd-output-data -i ${CMAKE_CURRENT_BINARY_DIR}/rocpd-input-data/out_results.db DEPENDS rocprofiler-sdk::rocprofv3 diff --git a/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/validate.py b/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/validate.py index 5c412dc1d39..4f2bdf7b352 100644 --- a/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/validate.py +++ b/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/validate.py @@ -71,6 +71,13 @@ def test_csv_data(csv_data, json_data): ) +def test_hip_event_annotations(pftrace_data, request): + import rocprofiler_sdk.tests.rocprofv3 as rocprofv3 + + pftrace_filename = request.config.getoption("--pftrace-input") + rocprofv3.test_perfetto_hip_event_annotations(pftrace_data, pftrace_filename) + + if __name__ == "__main__": exit_code = pytest.main(["-x", __file__] + sys.argv[1:]) sys.exit(exit_code) From fb5466cb000568f66d67dba36a1bac5935af93be Mon Sep 17 00:00:00 2001 From: Meng Cao Date: Tue, 10 Mar 2026 17:52:42 -0500 Subject: [PATCH 4/9] run formatters --- .../tests/pytest-packages/tests/rocprofv3.py | 8 ++------ .../rocprofiler-sdk/tests/rocprofv3/rocpd/CMakeLists.txt | 4 ++-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py b/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py index 3f46d27baaf..7ad7f34b8f1 100644 --- a/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py +++ b/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py @@ -577,9 +577,7 @@ def test_perfetto_hip_event_annotations(pftrace_data, pftrace_filename): # Check if we found any event handle annotations if result.empty: - pytest.skip( - "No HIP event API calls with event annotations found. " - ) + pytest.skip("No HIP event API calls with event annotations found. ") print(f"\n{len(result)} HIP event argument annotations found:") print(result.to_string()) @@ -598,9 +596,7 @@ def test_perfetto_hip_event_annotations(pftrace_data, pftrace_filename): # Validate that event values are present (non-null) null_values = result[result["arg_value"].isna()] - assert ( - null_values.empty - ), f"Found {len(null_values)} event arguments with null values" + assert null_values.empty, f"Found {len(null_values)} event arguments with null values" print( f"\nValidation passed: Found {len(result)} event handle annotations " diff --git a/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/CMakeLists.txt b/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/CMakeLists.txt index 56f9282e64f..d677489e59d 100644 --- a/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/CMakeLists.txt +++ b/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/CMakeLists.txt @@ -126,8 +126,8 @@ rocprofiler_add_integration_execute_test( rocprofiler_add_integration_execute_test( rocprofv3-test-rocpd-perfetto-generation COMMAND - ${Python3_EXECUTABLE} -m rocpd convert -f pftrace --kernel-rename --annotate-args -d - ${CMAKE_CURRENT_BINARY_DIR}/rocpd-output-data -i + ${Python3_EXECUTABLE} -m rocpd convert -f pftrace --kernel-rename --annotate-args + -d ${CMAKE_CURRENT_BINARY_DIR}/rocpd-output-data -i ${CMAKE_CURRENT_BINARY_DIR}/rocpd-input-data/out_results.db DEPENDS rocprofiler-sdk::rocprofv3 TIMEOUT 120 From f0580794f1e6c1e2c34778c119cc2106506eb37f Mon Sep 17 00:00:00 2001 From: Meng Cao Date: Wed, 11 Mar 2026 18:34:16 -0500 Subject: [PATCH 5/9] move annotation test (w/ --annotate-args) separate from original test --- .../tests/pytest-packages/tests/rocprofv3.py | 7 ++-- .../tests/rocprofv3/rocpd/CMakeLists.txt | 29 +++++++++++++- .../tests/rocprofv3/rocpd/validate.py | 7 ---- .../rocprofv3/rocpd/validate_annotations.py | 38 +++++++++++++++++++ 4 files changed, 69 insertions(+), 12 deletions(-) create mode 100644 projects/rocprofiler-sdk/tests/rocprofv3/rocpd/validate_annotations.py diff --git a/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py b/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py index 7ad7f34b8f1..1a974ca967b 100644 --- a/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py +++ b/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py @@ -575,9 +575,10 @@ def test_perfetto_hip_event_annotations(pftrace_data, pftrace_filename): result = reader.query_tp(query) - # Check if we found any event handle annotations - if result.empty: - pytest.skip("No HIP event API calls with event annotations found. ") + # Annotations must exist - perfetto was generated with --annotate-args + assert ( + not result.empty + ), "No HIP event annotations found - --annotate-args may be broken" print(f"\n{len(result)} HIP event argument annotations found:") print(result.to_string()) diff --git a/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/CMakeLists.txt b/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/CMakeLists.txt index d677489e59d..a58c3bca4ac 100644 --- a/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/CMakeLists.txt +++ b/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/CMakeLists.txt @@ -126,8 +126,8 @@ rocprofiler_add_integration_execute_test( rocprofiler_add_integration_execute_test( rocprofv3-test-rocpd-perfetto-generation COMMAND - ${Python3_EXECUTABLE} -m rocpd convert -f pftrace --kernel-rename --annotate-args - -d ${CMAKE_CURRENT_BINARY_DIR}/rocpd-output-data -i + ${Python3_EXECUTABLE} -m rocpd convert -f pftrace --kernel-rename -d + ${CMAKE_CURRENT_BINARY_DIR}/rocpd-output-data -i ${CMAKE_CURRENT_BINARY_DIR}/rocpd-input-data/out_results.db DEPENDS rocprofiler-sdk::rocprofv3 TIMEOUT 120 @@ -137,6 +137,20 @@ rocprofiler_add_integration_execute_test( FIXTURES_SETUP rocprofv3-test-rocpd-generation FIXTURES_REQUIRED rocprofv3-test-rocpd) +rocprofiler_add_integration_execute_test( + rocprofv3-test-rocpd-perfetto-generation-annotations + COMMAND + ${Python3_EXECUTABLE} -m rocpd convert -f pftrace --kernel-rename --annotate-args + -d ${CMAKE_CURRENT_BINARY_DIR}/rocpd-output-data-annotations -i + ${CMAKE_CURRENT_BINARY_DIR}/rocpd-input-data/out_results.db + DEPENDS rocprofiler-sdk::rocprofv3 + TIMEOUT 120 + LABELS "integration-tests;rocpd" + PRELOAD "${ROCPROFILER_MEMCHECK_PRELOAD_ENV_VALUE}" + ENVIRONMENT "${rocprofv3-rocpd-env}" + FIXTURES_SETUP rocprofv3-test-rocpd-generation-annotations + FIXTURES_REQUIRED rocprofv3-test-rocpd) + rocprofiler_add_integration_execute_test( rocprofv3-test-rocpd-perfetto-generation-multiproc COMMAND @@ -239,6 +253,17 @@ rocprofiler_add_integration_validate_test( LABELS "integration-tests;rocpd" FIXTURES_REQUIRED rocprofv3-test-rocpd-generation) +rocprofiler_add_integration_validate_test( + rocprofv3-test-rocpd-annotations + TEST_PATHS validate_annotations.py + COPY conftest.py + CONFIG pytest.ini + ARGS --pftrace-input + ${CMAKE_CURRENT_BINARY_DIR}/rocpd-output-data-annotations/out_results.pftrace + TIMEOUT 120 + LABELS "integration-tests;rocpd" + FIXTURES_REQUIRED rocprofv3-test-rocpd-generation-annotations) + ######################################################################################### # # Package generation diff --git a/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/validate.py b/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/validate.py index 4f2bdf7b352..5c412dc1d39 100644 --- a/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/validate.py +++ b/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/validate.py @@ -71,13 +71,6 @@ def test_csv_data(csv_data, json_data): ) -def test_hip_event_annotations(pftrace_data, request): - import rocprofiler_sdk.tests.rocprofv3 as rocprofv3 - - pftrace_filename = request.config.getoption("--pftrace-input") - rocprofv3.test_perfetto_hip_event_annotations(pftrace_data, pftrace_filename) - - if __name__ == "__main__": exit_code = pytest.main(["-x", __file__] + sys.argv[1:]) sys.exit(exit_code) diff --git a/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/validate_annotations.py b/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/validate_annotations.py new file mode 100644 index 00000000000..08778e2607c --- /dev/null +++ b/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/validate_annotations.py @@ -0,0 +1,38 @@ +#!/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_hip_event_annotations(pftrace_data, request): + import rocprofiler_sdk.tests.rocprofv3 as rocprofv3 + + pftrace_filename = request.config.getoption("--pftrace-input") + rocprofv3.test_perfetto_hip_event_annotations(pftrace_data, pftrace_filename) + + +if __name__ == "__main__": + exit_code = pytest.main(["-x", __file__] + sys.argv[1:]) + sys.exit(exit_code) From 475d41129f3579608d11bc2a8131807c3864496e Mon Sep 17 00:00:00 2001 From: Meng Cao Date: Mon, 16 Mar 2026 16:43:53 -0500 Subject: [PATCH 6/9] improve var naming --- .../source/lib/python/rocpd/source/perfetto.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/projects/rocprofiler-sdk/source/lib/python/rocpd/source/perfetto.cpp b/projects/rocprofiler-sdk/source/lib/python/rocpd/source/perfetto.cpp index 548f7cffa8a..4465a2aead4 100644 --- a/projects/rocprofiler-sdk/source/lib/python/rocpd/source/perfetto.cpp +++ b/projects/rocprofiler-sdk/source/lib/python/rocpd/source/perfetto.cpp @@ -460,9 +460,10 @@ write_perfetto( auto _pmc_events = read_pmc_events(itr.event_id); auto _event = (ocfg.annotate_kfd) ? read_event(itr.event_id) : types::event{}; - auto _canon = std::string_view{itr.name}; - auto want_event_handle_annotations = - ocfg.annotate_args && is_hip_event_api(_canon) && !is_event_create_api(_canon); + auto _api_name = std::string_view{itr.name}; + auto want_event_handle_annotations = ocfg.annotate_args && + is_hip_event_api(_api_name) && + !is_event_create_api(_api_name); auto _args = want_event_handle_annotations ? read_region_args(itr.id) : std::vector{}; From 688dc9c069022fdcfd1cdaae68c11ae40403fb57 Mon Sep 17 00:00:00 2001 From: Meng Cao Date: Mon, 16 Mar 2026 17:00:43 -0500 Subject: [PATCH 7/9] clean up rocprofv3.py --- .../rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py b/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py index 1a974ca967b..9ef6c48118f 100644 --- a/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py +++ b/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py @@ -580,11 +580,7 @@ def test_perfetto_hip_event_annotations(pftrace_data, pftrace_filename): not result.empty ), "No HIP event annotations found - --annotate-args may be broken" - print(f"\n{len(result)} HIP event argument annotations found:") - print(result.to_string()) - # Validate the structure - assert "slice_name" in result.columns assert "arg_name" in result.columns assert "arg_value" in result.columns From ca1ea6ec60597acea1bfff3181cf705ebe5ea4a8 Mon Sep 17 00:00:00 2001 From: Meng Cao Date: Tue, 17 Mar 2026 16:53:37 -0500 Subject: [PATCH 8/9] enable arg annotation for all instead of only event ID --- .../lib/python/rocpd/source/perfetto.cpp | 31 +------ .../tests/pytest-packages/tests/rocprofv3.py | 85 ++++++++----------- .../rocprofv3/rocpd/validate_annotations.py | 4 +- 3 files changed, 40 insertions(+), 80 deletions(-) diff --git a/projects/rocprofiler-sdk/source/lib/python/rocpd/source/perfetto.cpp b/projects/rocprofiler-sdk/source/lib/python/rocpd/source/perfetto.cpp index 4465a2aead4..a19f0ae831f 100644 --- a/projects/rocprofiler-sdk/source/lib/python/rocpd/source/perfetto.cpp +++ b/projects/rocprofiler-sdk/source/lib/python/rocpd/source/perfetto.cpp @@ -280,20 +280,6 @@ write_perfetto( "SELECT * FROM region_args WHERE guid='{}' AND id={}", process.guid, region_id)); }; - auto is_hip_event_api = [](std::string_view opname) { - return (opname.rfind("hipEvent", 0) == 0) || (opname == "hipStreamWaitEvent"); - }; - - auto is_event_create_api = [](std::string_view opname) { - return opname.rfind("hipEventCreate", 0) == 0; - }; - - auto is_hip_event_handle_arg = [](std::string_view argname) { - // - "event" for hipEventRecord/hipEventSynchronize/hipStreamWaitEvent - // - "start"/"stop" for hipEventElapsedTime - return (argname == "event") || (argname == "start") || (argname == "stop"); - }; - { for(auto ditr : memory_copy_gen) for(const auto& itr : memory_copy_gen.get(ditr)) @@ -460,12 +446,7 @@ write_perfetto( auto _pmc_events = read_pmc_events(itr.event_id); auto _event = (ocfg.annotate_kfd) ? read_event(itr.event_id) : types::event{}; - auto _api_name = std::string_view{itr.name}; - auto want_event_handle_annotations = ocfg.annotate_args && - is_hip_event_api(_api_name) && - !is_event_create_api(_api_name); - auto _args = want_event_handle_annotations ? read_region_args(itr.id) - : std::vector{}; + auto _args = read_region_args(itr.id); auto _category = ::perfetto::DynamicCategory{get_category_string(itr.category)}; TRACE_EVENT_BEGIN( @@ -527,15 +508,9 @@ write_perfetto( } } - if(want_event_handle_annotations) + for(const auto& a : _args) { - for(const auto& a : _args) - { - if(is_hip_event_handle_arg(a.name)) - { - rocprofiler::sdk::add_perfetto_annotation(ctx, a.name, a.value); - } - } + rocprofiler::sdk::add_perfetto_annotation(ctx, a.name, a.value); } }); diff --git a/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py b/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py index 9ef6c48118f..0c0b941fd52 100644 --- a/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py +++ b/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py @@ -518,29 +518,18 @@ def get_json_corr_id(x): _perform_csv_json_match(a, b, keys_mapping[category], json_data) -def test_perfetto_hip_event_annotations(pftrace_data, pftrace_filename): +def test_perfetto_arg_annotations(pftrace_data, pftrace_filename): """ - Test that HIP event API calls have event handle annotations in perfetto. - This validates the feature that adds event ID annotations for HIP event API arguments. - - The feature adds annotations for: - - hipEventRecord: 'event' argument - - hipEventSynchronize: 'event' argument - - hipEventElapsedTime: 'start' and 'stop' arguments - - hipStreamWaitEvent: 'event' argument - - Args: - pftrace_data: DataFrame with perfetto trace data - pftrace_filename: Path to the perfetto trace file for direct queries + Test that function argument annotations are available in perfetto with --annotate-args. + This validates that all API call arguments are annotated as debug annotations + across all categories (hip_api, marker_api, etc.). """ import pytest from rocprofiler_sdk.pytest_utils.perfetto_reader import PerfettoReader - # Filter for HIP API traces - hip_api_data = pftrace_data.loc[pftrace_data["category"] == "hip_api"] - - if hip_api_data.empty: - pytest.skip("No HIP API traces found") + # Check if trace has any data + if pftrace_data.empty: + pytest.skip("No trace data found") # Get the PerfettoReader to query the args table reader = PerfettoReader(pftrace_filename) @@ -549,53 +538,49 @@ def test_perfetto_hip_event_annotations(pftrace_data, pftrace_filename): if not reader.trace_processor: pytest.skip("Trace processor not available") - # Query for HIP event API slices and their arguments - # The args table joins with slice table on arg_set_id + # Query for API function argument annotations from --annotate-args + # Filter for hip_api/hsa_api/marker_api (KFD/kernel have args from other sources) + # Exclude metadata fields (always present, even without --annotate-args) query = """ SELECT slice.name as slice_name, + slice.category as slice_category, slice.id as slice_id, args.key as arg_name, args.string_value as arg_value FROM slice JOIN args ON slice.arg_set_id = args.arg_set_id - WHERE slice.category = 'hip_api' - AND ( - slice.name LIKE '%hipEventRecord%' OR - slice.name LIKE '%hipEventSynchronize%' OR - slice.name LIKE '%hipEventElapsedTime%' OR - slice.name LIKE '%hipStreamWaitEvent%' - ) - AND ( - args.key = 'debug.event' OR - args.key = 'debug.start' OR - args.key = 'debug.stop' + WHERE args.key LIKE 'debug.%' + AND slice.category IN ('hip_api', 'hsa_api', 'marker_api') + AND args.key NOT IN ( + 'debug.begin_ns', 'debug.end_ns', 'debug.delta_ns', + 'debug.tid', 'debug.kind', 'debug.operation', + 'debug.corr_id', 'debug.ancestor_id' ) """ result = reader.query_tp(query) - # Annotations must exist - perfetto was generated with --annotate-args - assert ( - not result.empty - ), "No HIP event annotations found - --annotate-args may be broken" + # Function argument annotations must exist - perfetto was generated with --annotate-args + assert not result.empty, ( + "No function argument annotations found - --annotate-args may be broken. " + "Only metadata fields were found, which are always present." + ) # Validate the structure + assert "slice_name" in result.columns + assert "slice_category" in result.columns assert "arg_name" in result.columns assert "arg_value" in result.columns - # Validate that we have expected argument names - found_arg_names = set(result["arg_name"].unique()) - expected_arg_names = {"debug.event", "debug.start", "debug.stop"} - assert found_arg_names.issubset( - expected_arg_names - ), f"Found unexpected arg names: {found_arg_names - expected_arg_names}" - - # Validate that event values are present (non-null) - null_values = result[result["arg_value"].isna()] - assert null_values.empty, f"Found {len(null_values)} event arguments with null values" - - print( - f"\nValidation passed: Found {len(result)} event handle annotations " - f"with arg names: {found_arg_names}" - ) + # Get statistics for debugging + unique_slices = result["slice_name"].nunique() + unique_args = result["arg_name"].nunique() + unique_categories = result["slice_category"].nunique() + categories = result["slice_category"].unique() + + print(f"\nValidation passed: Found {len(result)} argument annotations") + print(f" - {unique_slices} unique API calls annotated") + print(f" - {unique_categories} categories: {list(categories)}") + print(f" - {unique_args} unique argument types") + print(f" - Sample argument names: {list(result['arg_name'].unique()[:10])}") diff --git a/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/validate_annotations.py b/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/validate_annotations.py index 08778e2607c..ff0e7545b20 100644 --- a/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/validate_annotations.py +++ b/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/validate_annotations.py @@ -26,11 +26,11 @@ import pytest -def test_hip_event_annotations(pftrace_data, request): +def test_arg_annotations(pftrace_data, request): import rocprofiler_sdk.tests.rocprofv3 as rocprofv3 pftrace_filename = request.config.getoption("--pftrace-input") - rocprofv3.test_perfetto_hip_event_annotations(pftrace_data, pftrace_filename) + rocprofv3.test_perfetto_arg_annotations(pftrace_data, pftrace_filename) if __name__ == "__main__": From 529981137dfe6c400d49837cd94900377b671cb5 Mon Sep 17 00:00:00 2001 From: Meng Cao Date: Fri, 20 Mar 2026 14:29:17 -0500 Subject: [PATCH 9/9] cleanup: remove unnecessary PerfettoReader call --- .../tests/pytest-packages/tests/rocprofv3.py | 16 ++-------------- .../tests/rocprofv3/rocpd/conftest.py | 9 +++++++-- .../rocprofv3/rocpd/validate_annotations.py | 5 ++--- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py b/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py index 0c0b941fd52..f8311e733c6 100644 --- a/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py +++ b/projects/rocprofiler-sdk/tests/pytest-packages/tests/rocprofv3.py @@ -518,25 +518,13 @@ def get_json_corr_id(x): _perform_csv_json_match(a, b, keys_mapping[category], json_data) -def test_perfetto_arg_annotations(pftrace_data, pftrace_filename): +def test_perfetto_arg_annotations(pftrace_reader): """ Test that function argument annotations are available in perfetto with --annotate-args. This validates that all API call arguments are annotated as debug annotations across all categories (hip_api, marker_api, etc.). """ import pytest - from rocprofiler_sdk.pytest_utils.perfetto_reader import PerfettoReader - - # Check if trace has any data - if pftrace_data.empty: - pytest.skip("No trace data found") - - # Get the PerfettoReader to query the args table - reader = PerfettoReader(pftrace_filename) - - # Access the trace processor directly - if not reader.trace_processor: - pytest.skip("Trace processor not available") # Query for API function argument annotations from --annotate-args # Filter for hip_api/hsa_api/marker_api (KFD/kernel have args from other sources) @@ -559,7 +547,7 @@ def test_perfetto_arg_annotations(pftrace_data, pftrace_filename): ) """ - result = reader.query_tp(query) + result = pftrace_reader.query_tp(query) # Function argument annotations must exist - perfetto was generated with --annotate-args assert not result.empty, ( diff --git a/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/conftest.py b/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/conftest.py index af17f431721..4a25ae3e92d 100644 --- a/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/conftest.py +++ b/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/conftest.py @@ -82,9 +82,14 @@ def json_data(request): @pytest.fixture -def pftrace_data(request): +def pftrace_reader(request): filename = request.config.getoption("--pftrace-input") - return PerfettoReader(filename).read()[0] + return PerfettoReader(filename) + + +@pytest.fixture +def pftrace_data(pftrace_reader): + return pftrace_reader.read()[0] @pytest.fixture diff --git a/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/validate_annotations.py b/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/validate_annotations.py index ff0e7545b20..491b5319fdd 100644 --- a/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/validate_annotations.py +++ b/projects/rocprofiler-sdk/tests/rocprofv3/rocpd/validate_annotations.py @@ -26,11 +26,10 @@ import pytest -def test_arg_annotations(pftrace_data, request): +def test_arg_annotations(pftrace_reader): import rocprofiler_sdk.tests.rocprofv3 as rocprofv3 - pftrace_filename = request.config.getoption("--pftrace-input") - rocprofv3.test_perfetto_arg_annotations(pftrace_data, pftrace_filename) + rocprofv3.test_perfetto_arg_annotations(pftrace_reader) if __name__ == "__main__":