From 3d7a5eec0e320006faadd531c47febc9f73ab269 Mon Sep 17 00:00:00 2001 From: David Galiffi Date: Tue, 28 Oct 2025 13:06:07 -0400 Subject: [PATCH] Setup `rocprofsys_root` environment variable (#1561) * Setup `rocprofsys_root` environment variable * Update `CHANGELOGS` * Fixed formatting * Add rocpd output and validation to python tests * Refactoring environment setup --- projects/rocprofiler-systems/CHANGELOG.md | 4 + .../source/python/rocprofsys/__init__.py | 15 ++- .../python/python-builtin-rules.json | 77 +++++++++++++ .../python/python-source-rules.json | 105 ++++++++++++++++++ .../tests/rocprof-sys-python-tests.cmake | 30 ++++- .../tests/rocprof-sys-testing.cmake | 7 ++ 6 files changed, 234 insertions(+), 4 deletions(-) create mode 100644 projects/rocprofiler-systems/tests/rocpd-validation-rules/python/python-builtin-rules.json create mode 100644 projects/rocprofiler-systems/tests/rocpd-validation-rules/python/python-source-rules.json diff --git a/projects/rocprofiler-systems/CHANGELOG.md b/projects/rocprofiler-systems/CHANGELOG.md index c60f3a19ff..a196326b0a 100644 --- a/projects/rocprofiler-systems/CHANGELOG.md +++ b/projects/rocprofiler-systems/CHANGELOG.md @@ -15,6 +15,10 @@ Full documentation for ROCm Systems Profiler is available at [https://rocm.docs. - Improved Fortran main function detection to ensure `rocprof-sys-instrument` uses the Fortran program main function instead of the C wrapper. +### Resolved issues + +- Fixed a crash when running `rocprof-sys-python` with ROCPROFSYS_USE_ROCPD enabled. + ## ROCm Systems Profiler 1.2.0 for ROCm 7.1.0 ### Added diff --git a/projects/rocprofiler-systems/source/python/rocprofsys/__init__.py b/projects/rocprofiler-systems/source/python/rocprofsys/__init__.py index 24a7962ef9..adc8b44118 100644 --- a/projects/rocprofiler-systems/source/python/rocprofsys/__init__.py +++ b/projects/rocprofiler-systems/source/python/rocprofsys/__init__.py @@ -24,7 +24,7 @@ from __future__ import absolute_import __author__ = "AMD ROCm" -__copyright__ = "Copyright 2024, Advanced Micro Devices, Inc." +__copyright__ = "Copyright 2025, Advanced Micro Devices, Inc." __license__ = "MIT" __version__ = "@PROJECT_VERSION@" __maintainer__ = "AMD ROCm" @@ -36,9 +36,18 @@ This submodule imports the timemory Python function profiler try: import os + from pathlib import Path - os.environ["ROCPROFSYS_PATH"] = os.path.abspath( - os.path.join(os.path.dirname(__file__), "../../..") + # Set up ROCPROFSYS environment variables + rocprofsys_root = Path(__file__).resolve().parents[4] + os.environ.update( + { + "ROCPROFSYS_ROOT": str(rocprofsys_root), + "ROCPROFSYS_PATH": str(rocprofsys_root / "lib"), + "ROCPROFSYS_SCRIPT_PATH": str( + rocprofsys_root / "libexec/rocprofiler-systems" + ), + } ) from .libpyrocprofsys import coverage diff --git a/projects/rocprofiler-systems/tests/rocpd-validation-rules/python/python-builtin-rules.json b/projects/rocprofiler-systems/tests/rocpd-validation-rules/python/python-builtin-rules.json new file mode 100644 index 0000000000..9fa8eb40c0 --- /dev/null +++ b/projects/rocprofiler-systems/tests/rocpd-validation-rules/python/python-builtin-rules.json @@ -0,0 +1,77 @@ +{ + "required_tables": [ + { + "commit": "Validation rules for python-builtin tests", + "name": "top", + "required_columns": [ + "total_calls", + "total_duration", + "average", + "percentage" + ], + "validation_queries": [ + { + "comparison": "equals", + "description": "Verify that '[run][builtin.py:31]' has a total of 5 calls.", + "error_message": "'[run][builtin.py:31]' does not have 5 total calls, as expected.", + "expected_result": 5, + "query": "SELECT total_calls FROM top WHERE name = '[run][builtin.py:31]';" + }, + { + "comparison": "equals", + "description": "Verify that '[inefficient][builtin.py:17]' has a total of 5 calls.", + "error_message": "'[inefficient][builtin.py:17]' does not have 5 total calls, as expected.", + "expected_result": 5, + "query": "SELECT total_calls FROM top WHERE name = '[inefficient][builtin.py:17]';" + }, + { + "comparison": "equals", + "description": "Verify that '[fib][builtin.py:13]' has a total of 445 calls.", + "error_message": "'[fib][builtin.py:13]' does not have 445 total calls, as expected.", + "expected_result": 445, + "query": "SELECT total_calls FROM top WHERE name = '[fib][builtin.py:13]';" + }, + { + "comparison": "equals", + "description": "Verify that percentages sum to 100.", + "error_message": "Percentages do not sum to 100.", + "expected_result": 100, + "query": "SELECT SUM(percentage) FROM top;" + } + ] + }, + { + "commit": "", + "name": "regions", + "required_columns": [ + "id", + "guid", + "category", + "name" + ], + "validation_queries": [ + { + "comparison": "equals", + "description": "Verify that '[run][builtin.py:31]' has a total of 5 calls.", + "error_message": "'[run][builtin.py:31]' does not have 5 total calls, as expected.", + "expected_result": 5, + "query": "SELECT COUNT(*) FROM regions WHERE name = '[run][builtin.py:31]';" + }, + { + "comparison": "equals", + "description": "Verify that '[inefficient][builtin.py:17]' has a total of 5 calls.", + "error_message": "'[inefficient][builtin.py:17]' does not have 5 total calls, as expected.", + "expected_result": 5, + "query": "SELECT COUNT(*) FROM regions WHERE name = '[inefficient][builtin.py:17]';" + }, + { + "comparison": "equals", + "description": "Verify that '[fib][builtin.py:13]' has a total of 445 calls.", + "error_message": "'[fib][builtin.py:13] does not have 445 total calls, as expected.", + "expected_result": 445, + "query": "SELECT COUNT(*) FROM regions WHERE name = '[fib][builtin.py:13]';" + } + ] + } + ] +} diff --git a/projects/rocprofiler-systems/tests/rocpd-validation-rules/python/python-source-rules.json b/projects/rocprofiler-systems/tests/rocpd-validation-rules/python/python-source-rules.json new file mode 100644 index 0000000000..0abc9bc75f --- /dev/null +++ b/projects/rocprofiler-systems/tests/rocpd-validation-rules/python/python-source-rules.json @@ -0,0 +1,105 @@ +{ + "required_tables": [ + { + "commit": "Validation rules for python-builtin tests", + "name": "top", + "required_columns": [ + "total_calls", + "total_duration", + "average", + "percentage" + ], + "validation_queries": [ + { + "comparison": "equals", + "description": "Verify that 'main_loop' has a total of 5 calls.", + "error_message": "'main_loop' does not have 5 total calls, as expected.", + "expected_result": 5, + "query": "SELECT total_calls FROM top WHERE name = 'main_loop';" + }, + { + "comparison": "equals", + "description": "Verify that 'run' has a total of 3 calls.", + "error_message": "'run' does not have 3 total calls, as expected.", + "expected_result": 3, + "query": "SELECT total_calls FROM top WHERE name = 'run';" + }, + { + "comparison": "equals", + "description": "Verify that 'inefficient' has a total of 3 calls.", + "error_message": "'inefficient' does not have 3 total calls, as expected.", + "expected_result": 3, + "query": "SELECT total_calls FROM top WHERE name = 'inefficient';" + }, + { + "comparison": "equals", + "description": "Verify that '_sum' has a total of 3 calls.", + "error_message": "'_sum' does not have 3 total calls, as expected.", + "expected_result": 3, + "query": "SELECT total_calls FROM top WHERE name = '_sum';" + }, + { + "comparison": "equals", + "description": "Verify that 'fib' has a total of 3 calls.", + "error_message": "'fib' does not have 24 total calls, as expected.", + "expected_result": 24, + "query": "SELECT total_calls FROM top WHERE name = 'fib';" + }, + { + "comparison": "equals", + "description": "Verify that percentages sum to 100.", + "error_message": "Percentages do not sum to 100.", + "expected_result": 100, + "query": "SELECT SUM(percentage) FROM top;" + } + ] + }, + { + "commit": "", + "name": "regions", + "required_columns": [ + "id", + "guid", + "category", + "name" + ], + "validation_queries": [ + { + "comparison": "equals", + "description": "Verify that 'main_loop' has a total of 5 calls.", + "error_message": "'main_loop' does not have 5 total calls, as expected.", + "expected_result": 5, + "query": "SELECT COUNT(*) FROM regions WHERE name = 'main_loop';" + }, + { + "comparison": "equals", + "description": "Verify that 'run' has a total of 3 calls.", + "error_message": "'run' does not have 3 total calls, as expected.", + "expected_result": 3, + "query": "SELECT COUNT(*) FROM regions WHERE name = 'run';" + }, + { + "comparison": "equals", + "description": "Verify that 'inefficient' has a total of 3 calls.", + "error_message": "'inefficient' does not have 3 total calls, as expected.", + "expected_result": 3, + "query": "SELECT COUNT(*) FROM regions WHERE name = 'inefficient';" + }, + { + "comparison": "equals", + "description": "Verify that '_sum' has a total of 3 calls.", + "error_message": "'_sum' does not have 3 total calls, as expected.", + "expected_result": 3, + "query": "SELECT COUNT(*) FROM regions WHERE name = '_sum';" + }, + { + "comparison": "equals", + "description": "Verify that 'fib' has a total of 24 calls.", + "error_message": "'fib' does not have 24 total calls, as expected.", + "expected_result": 24, + "query": "SELECT COUNT(*) FROM regions WHERE name = 'fib';" + } + ] + } + ] +} diff --git a/projects/rocprofiler-systems/tests/rocprof-sys-python-tests.cmake b/projects/rocprofiler-systems/tests/rocprof-sys-python-tests.cmake index c6d7ed9319..ed0426dc01 100644 --- a/projects/rocprofiler-systems/tests/rocprof-sys-python-tests.cmake +++ b/projects/rocprofiler-systems/tests/rocprof-sys-python-tests.cmake @@ -161,7 +161,7 @@ foreach(_VERSION ${ROCPROFSYS_PYTHON_VERSIONS}) TEST "" "NAME;TIMEMORY_METRIC;TIMEMORY_FILE;PERFETTO_FILE" - "ARGS;PERFETTO_METRIC" + "ARGS;PERFETTO_METRIC;ROCPD_FILE;ROCPD_RULES" ${ARGN} ) @@ -191,6 +191,27 @@ foreach(_VERSION ${ROCPROFSYS_PYTHON_VERSIONS}) "rocprof-sys-tests-output/${TEST_NAME}/${_VERSION}/${TEST_PERFETTO_FILE} validated" ENVIRONMENT "${_python_environment}" ) + + if( + ${ENABLE_ROCPD_TEST} + AND ${_VALID_GPU} + AND TEST_ROCPD_FILE + AND TEST_ROCPD_RULES + ) + rocprofiler_systems_add_python_test( + NAME ${TEST_NAME}-validate-rocpd + COMMAND + ${_PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/validate-rocpd.py + -r ${TEST_ROCPD_RULES} -db + PYTHON_VERSION ${_VERSION} + FILE rocprof-sys-tests-output/${TEST_NAME}/${_VERSION}/${TEST_ROCPD_FILE} + DEPENDS ${TEST_NAME}-${_VERSION} + PASS_REGEX + "rocprof-sys-tests-output/${TEST_NAME}/${_VERSION}/${TEST_ROCPD_FILE} validated" + ENVIRONMENT "${_python_environment}" + LABELS "rocpd" + ) + endif() endfunction() set(python_source_labels @@ -237,6 +258,9 @@ foreach(_VERSION ${ROCPROFSYS_PYTHON_VERSIONS}) PERFETTO_METRIC ${python_source_categories} ARGS -l ${python_source_labels} -c ${python_source_count} -d ${python_source_depth} + ROCPD_FILE "rocpd.db" + ROCPD_RULES + "${CMAKE_CURRENT_LIST_DIR}/rocpd-validation-rules/python/python-source-rules.json" ) set(python_builtin_labels @@ -290,6 +314,10 @@ foreach(_VERSION ${ROCPROFSYS_PYTHON_VERSIONS}) PERFETTO_FILE "perfetto-trace.proto" ARGS -l ${python_builtin_labels} -c ${python_builtin_count} -d ${python_builtin_depth} + ROCPD_FILE "rocpd.db" + ROCPD_RULES + "${CMAKE_CURRENT_LIST_DIR}/rocpd-validation-rules/python/python-builtin-rules.json" ) + math(EXPR _INDEX "${_INDEX} + 1") endforeach() diff --git a/projects/rocprofiler-systems/tests/rocprof-sys-testing.cmake b/projects/rocprofiler-systems/tests/rocprof-sys-testing.cmake index 89866c3fde..d4c94bbae6 100644 --- a/projects/rocprofiler-systems/tests/rocprof-sys-testing.cmake +++ b/projects/rocprofiler-systems/tests/rocprof-sys-testing.cmake @@ -1024,7 +1024,14 @@ function(ROCPROFILER_SYSTEMS_ADD_PYTHON_TEST) set(_TEST_FILE ${PROJECT_BINARY_DIR}/python/tests/${TEST_PYTHON_VERSION}/${_TEST_FILE} ) + + if(${ENABLE_ROCPD_TEST} AND ${_VALID_GPU}) + list(APPEND TEST_LABELS "rocpd") + list(APPEND TEST_ENVIRONMENT "ROCPROFSYS_USE_ROCPD=ON") + endif() + configure_file(${TEST_FILE} ${_TEST_FILE} @ONLY) + if(TEST_STANDALONE) add_test( NAME ${TEST_NAME}-${TEST_PYTHON_VERSION}