From 9f014db6a42d9e893127ea57ad9cc27e9c7445b5 Mon Sep 17 00:00:00 2001 From: Kian Cossettini Date: Thu, 15 Jan 2026 21:51:16 -0500 Subject: [PATCH 01/21] [rocprofiler-systems] Update install path for examples (#2625) * Update install path for examples to `share/rocprofiler-systems/examples` ---- Co-authored-by: Kian Cossettini Signed-off-by: David Galiffi --- .../examples/causal-helpers.cmake | 29 ++++++++++++--- .../examples/code-coverage/CMakeLists.txt | 11 ++++-- .../examples/fork/CMakeLists.txt | 15 ++++++-- .../examples/jpegdecode/CMakeLists.txt | 36 ++++++------------- .../examples/lulesh/CMakeLists.txt | 20 +++++------ .../examples/mpi/CMakeLists.txt | 33 +++++++++++------ .../examples/openmp/CMakeLists.txt | 18 ++++++---- .../examples/openmp/external/CMakeLists.txt | 16 +++++++++ .../examples/openmp/target/CMakeLists.txt | 14 +++++++- .../examples/parallel-overhead/CMakeLists.txt | 20 +++++++---- .../examples/python/CMakeLists.txt | 5 ++- .../examples/rccl/CMakeLists.txt | 8 +++++ .../examples/rewrite-caller/CMakeLists.txt | 11 ++++-- .../examples/roctx/CMakeLists.txt | 31 +++++----------- .../examples/thread-limit/CMakeLists.txt | 8 +++++ .../examples/trace-time-window/CMakeLists.txt | 7 ++-- .../examples/transferBench/CMakeLists.txt | 11 ++++-- .../examples/transpose/CMakeLists.txt | 11 ++++-- .../examples/user-api/CMakeLists.txt | 11 ++++-- .../examples/videodecode/CMakeLists.txt | 11 +++--- 20 files changed, 215 insertions(+), 111 deletions(-) diff --git a/projects/rocprofiler-systems/examples/causal-helpers.cmake b/projects/rocprofiler-systems/examples/causal-helpers.cmake index 7a472f4058..5a66833565 100644 --- a/projects/rocprofiler-systems/examples/causal-helpers.cmake +++ b/projects/rocprofiler-systems/examples/causal-helpers.cmake @@ -1,3 +1,6 @@ +# Copyright (c) Advanced Micro Devices, Inc. +# SPDX-License-Identifier: MIT + # # function for # @@ -142,11 +145,27 @@ function(rocprofiler_systems_causal_example_executable _NAME) endif() if(ROCPROFSYS_INSTALL_EXAMPLES) - install( - TARGETS ${_NAME} ${_NAME}-rocprofsys ${_NAME}-coz - DESTINATION bin - COMPONENT rocprofiler-systems-examples - OPTIONAL + set(_TARGETS + ${_NAME} + ${_NAME}-rocprofsys + ${_NAME}-ndebug + ${_NAME}-rocprofsys-ndebug + ${_NAME}-coz ) + set(_EXISTING_TARGETS) + + foreach(_TARGET IN LISTS _TARGETS) + if(TARGET ${_TARGET}) + list(APPEND _EXISTING_TARGETS ${_TARGET}) + endif() + endforeach() + + if(_EXISTING_TARGETS) + install( + TARGETS ${_EXISTING_TARGETS} + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples + COMPONENT rocprofiler-systems-examples + ) + endif() endif() endfunction() diff --git a/projects/rocprofiler-systems/examples/code-coverage/CMakeLists.txt b/projects/rocprofiler-systems/examples/code-coverage/CMakeLists.txt index 60d474bd23..c25ef91312 100644 --- a/projects/rocprofiler-systems/examples/code-coverage/CMakeLists.txt +++ b/projects/rocprofiler-systems/examples/code-coverage/CMakeLists.txt @@ -1,3 +1,6 @@ +# Copyright (c) Advanced Micro Devices, Inc. +# SPDX-License-Identifier: MIT + cmake_minimum_required(VERSION 3.21 FATAL_ERROR) project(rocprofiler-systems-code-coverage-example LANGUAGES CXX) @@ -22,7 +25,11 @@ target_link_libraries(code-coverage PRIVATE Threads::Threads) target_compile_options(code-coverage PRIVATE ${_FLAGS}) if(ROCPROFSYS_INSTALL_EXAMPLES) - install(TARGETS code-coverage DESTINATION bin COMPONENT rocprofiler-systems-examples) + install( + TARGETS code-coverage + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples + COMPONENT rocprofiler-systems-examples + ) endif() set(PYTHON_FILES code-coverage.py) @@ -42,7 +49,7 @@ if(Python3_FOUND) if(ROCPROFSYS_INSTALL_EXAMPLES) install( PROGRAMS ${PROJECT_BINARY_DIR}/${_FILE} - DESTINATION bin + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples COMPONENT rocprofiler-systems-examples ) endif() diff --git a/projects/rocprofiler-systems/examples/fork/CMakeLists.txt b/projects/rocprofiler-systems/examples/fork/CMakeLists.txt index 5a54900e61..af72c34ecc 100644 --- a/projects/rocprofiler-systems/examples/fork/CMakeLists.txt +++ b/projects/rocprofiler-systems/examples/fork/CMakeLists.txt @@ -1,3 +1,6 @@ +# Copyright (c) Advanced Micro Devices, Inc. +# SPDX-License-Identifier: MIT + cmake_minimum_required(VERSION 3.21 FATAL_ERROR) project(rocprofiler-systems-fork LANGUAGES CXX) @@ -18,7 +21,13 @@ target_link_libraries( target_compile_options(fork-example PRIVATE ${_FLAGS}) if(ROCPROFSYS_INSTALL_EXAMPLES) - install(TARGETS fork-example DESTINATION bin COMPONENT rocprofiler-systems-examples) + if(TARGET fork-example) + install( + TARGETS fork-example + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples + COMPONENT rocprofiler-systems-examples + ) + endif() endif() # HIP fork example (multi-process concurrency test) @@ -81,10 +90,10 @@ if(HIPCC_EXECUTABLE) rocprofiler_systems_custom_compilation(COMPILER ${HIPCC_EXECUTABLE} TARGET hipMallocConcurrencyMproc) endif() - if(ROCPROFSYS_INSTALL_EXAMPLES) + if(ROCPROFSYS_INSTALL_EXAMPLES AND TARGET hipMallocConcurrencyMproc) install( TARGETS hipMallocConcurrencyMproc - DESTINATION bin + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples COMPONENT rocprofiler-systems-examples ) endif() diff --git a/projects/rocprofiler-systems/examples/jpegdecode/CMakeLists.txt b/projects/rocprofiler-systems/examples/jpegdecode/CMakeLists.txt index ba5bc9fb6b..992d0272d2 100644 --- a/projects/rocprofiler-systems/examples/jpegdecode/CMakeLists.txt +++ b/projects/rocprofiler-systems/examples/jpegdecode/CMakeLists.txt @@ -1,25 +1,5 @@ -################################################################################ -# Copyright (c) 2024 - 2025 Advanced Micro Devices, Inc. -# -# 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. -# -################################################################################ +# Copyright (c) Advanced Micro Devices, Inc. +# SPDX-License-Identifier: MIT cmake_minimum_required(VERSION 3.21 FATAL_ERROR) @@ -157,11 +137,15 @@ if(HIP_FOUND AND rocjpeg_FOUND AND Threads_FOUND AND rocprofiler-register_FOUND) target_compile_options(jpegdecode PRIVATE ${_FLAGS}) copy_image_files_and_make_copies() - if(ROCPROFSYS_INSTALL_EXAMPLES) - install(TARGETS jpegdecode DESTINATION bin COMPONENT rocprofiler-systems-examples) + if(ROCPROFSYS_INSTALL_EXAMPLES AND TARGET jpegdecode) install( - FILES ${CMAKE_BINARY_DIR}/images - DESTINATION share/rocprofiler-systems/tests/images + TARGETS jpegdecode + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples + COMPONENT rocprofiler-systems-examples + ) + install( + DIRECTORY ${CMAKE_BINARY_DIR}/images/ + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples/images COMPONENT rocprofiler-systems-examples ) endif() diff --git a/projects/rocprofiler-systems/examples/lulesh/CMakeLists.txt b/projects/rocprofiler-systems/examples/lulesh/CMakeLists.txt index 9fd7935d3e..62dc292e2a 100644 --- a/projects/rocprofiler-systems/examples/lulesh/CMakeLists.txt +++ b/projects/rocprofiler-systems/examples/lulesh/CMakeLists.txt @@ -1,3 +1,6 @@ +# Copyright (c) Advanced Micro Devices, Inc. +# SPDX-License-Identifier: MIT + cmake_minimum_required(VERSION 3.21 FATAL_ERROR) project(rocprofiler-systems-lulesh-example LANGUAGES C CXX) @@ -82,16 +85,11 @@ rocprofiler_systems_causal_example_executable( INCLUDE_DIRECTORIES ${PROJECT_SOURCE_DIR}/includes ) -if(ROCPROFSYS_INSTALL_EXAMPLES) - if(LULESH_BUILD_KOKKOS) - install( - TARGETS kokkoscore kokkoscontainers - DESTINATION ${CMAKE_INSTALL_LIBDIR} +if(ROCPROFSYS_INSTALL_EXAMPLES AND LULESH_BUILD_KOKKOS) + install( + TARGETS kokkoscore kokkoscontainers kokkossimd + LIBRARY + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples/lib COMPONENT rocprofiler-systems-examples - ) - set_target_properties( - lulesh - PROPERTIES INSTALL_RPATH "\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}" - ) - endif() + ) endif() diff --git a/projects/rocprofiler-systems/examples/mpi/CMakeLists.txt b/projects/rocprofiler-systems/examples/mpi/CMakeLists.txt index 2ff4043a3c..80a4a70c47 100644 --- a/projects/rocprofiler-systems/examples/mpi/CMakeLists.txt +++ b/projects/rocprofiler-systems/examples/mpi/CMakeLists.txt @@ -1,3 +1,6 @@ +# Copyright (c) Advanced Micro Devices, Inc. +# SPDX-License-Identifier: MIT + cmake_minimum_required(VERSION 3.21 FATAL_ERROR) project(rocprofiler-systems-mpi-examples LANGUAGES C CXX) @@ -77,16 +80,24 @@ add_executable(mpi-example mpi.cpp) target_link_libraries(mpi-example PRIVATE mpi-cxx-interface-library) if(ROCPROFSYS_INSTALL_EXAMPLES) - install( - TARGETS - mpi-example - mpi-allgather - mpi-bcast - mpi-all2all - mpi-reduce - mpi-scatter-gather - mpi-send-recv - DESTINATION bin - COMPONENT rocprofiler-systems-examples + set(MPI_EXAMPLES + mpi-example + mpi-allgather + mpi-bcast + mpi-all2all + mpi-reduce + mpi-scatter-gather + mpi-send-recv + mpi-allreduce ) + + foreach(MPI_EXAMPLE IN LISTS MPI_EXAMPLES) + if(TARGET ${MPI_EXAMPLE}) + install( + TARGETS ${MPI_EXAMPLE} + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples + COMPONENT rocprofiler-systems-examples + ) + endif() + endforeach() endif() diff --git a/projects/rocprofiler-systems/examples/openmp/CMakeLists.txt b/projects/rocprofiler-systems/examples/openmp/CMakeLists.txt index 9e0302b73b..079a10516d 100644 --- a/projects/rocprofiler-systems/examples/openmp/CMakeLists.txt +++ b/projects/rocprofiler-systems/examples/openmp/CMakeLists.txt @@ -89,13 +89,17 @@ endif() target_link_libraries(openmp-cg PRIVATE openmp-common) target_link_libraries(openmp-lu PRIVATE openmp-common) -if(ROCPROFSYS_INSTALL_EXAMPLES) - install( - TARGETS openmp-cg openmp-lu - DESTINATION bin - COMPONENT rocprofiler-systems-examples - ) -endif() +set(OPENMP_EXAMPLES openmp-cg openmp-lu) + +foreach(OPENMP_EXAMPLE IN LISTS OPENMP_EXAMPLES) + if(ROCPROFSYS_INSTALL_EXAMPLES AND TARGET ${OPENMP_EXAMPLE}) + install( + TARGETS ${OPENMP_EXAMPLE} + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples + COMPONENT rocprofiler-systems-examples + ) + endif() +endforeach() set(DEFAULT_GPU_TARGETS "gfx900" diff --git a/projects/rocprofiler-systems/examples/openmp/external/CMakeLists.txt b/projects/rocprofiler-systems/examples/openmp/external/CMakeLists.txt index 5c184187a8..bc502d2e42 100644 --- a/projects/rocprofiler-systems/examples/openmp/external/CMakeLists.txt +++ b/projects/rocprofiler-systems/examples/openmp/external/CMakeLists.txt @@ -280,3 +280,19 @@ set(ROCPROFSYS_OMPVV_OFFLOAD_TESTS rocprofiler_systems_message(STATUS "Successfully configured OMPVV" ) + +if(ROCPROFSYS_INSTALL_EXAMPLES) + foreach( + test_target + IN + LISTS ROCPROFSYS_OMPVV_HOST_TESTS ROCPROFSYS_OMPVV_OFFLOAD_TESTS + ) + if(TARGET "${test_target}-build") + install( + PROGRAMS "${OMPVV_BIN_DEST}/${test_target}" + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples + COMPONENT rocprofiler-systems-examples + ) + endif() + endforeach() +endif() diff --git a/projects/rocprofiler-systems/examples/openmp/target/CMakeLists.txt b/projects/rocprofiler-systems/examples/openmp/target/CMakeLists.txt index af4a70ca4b..d9a3e05857 100644 --- a/projects/rocprofiler-systems/examples/openmp/target/CMakeLists.txt +++ b/projects/rocprofiler-systems/examples/openmp/target/CMakeLists.txt @@ -71,7 +71,7 @@ endif() # Use the directory that actually contains the library we found get_filename_component(_rocm_llvm_lib "${LIBOMPTARGET_SO}" DIRECTORY) set(_rocm_clang_lib "${ROCM_ROOT_DIR}/lib") -set(_COMMON_RPATH "${_rocm_llvm_lib};${_rocm_clang_lib};$ORIGIN") +set(_COMMON_RPATH "${_rocm_llvm_lib};${_rocm_clang_lib};$ORIGIN;$ORIGIN/lib") if(ROCmVersion_DIR) list(APPEND _COMMON_RPATH "${ROCmVersion_DIR}/llvm/lib") endif() @@ -126,3 +126,15 @@ rocprofiler_systems_custom_compilation( rocprofiler_systems_custom_compilation(TARGET openmp-target COMPILER ${OMP_TARGET_COMPILER} ) + +if(ROCPROFSYS_INSTALL_EXAMPLES) + if(TARGET openmp-target AND TARGET openmp-target-lib) + install( + TARGETS openmp-target openmp-target-lib + RUNTIME DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples + LIBRARY + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples/lib + COMPONENT rocprofiler-systems-examples + ) + endif() +endif() diff --git a/projects/rocprofiler-systems/examples/parallel-overhead/CMakeLists.txt b/projects/rocprofiler-systems/examples/parallel-overhead/CMakeLists.txt index 8737781185..452923551b 100644 --- a/projects/rocprofiler-systems/examples/parallel-overhead/CMakeLists.txt +++ b/projects/rocprofiler-systems/examples/parallel-overhead/CMakeLists.txt @@ -1,3 +1,6 @@ +# Copyright (c) Advanced Micro Devices, Inc. +# SPDX-License-Identifier: MIT + cmake_minimum_required(VERSION 3.21 FATAL_ERROR) project(rocprofiler-systems-parallel-overhead-example LANGUAGES CXX) @@ -32,10 +35,13 @@ target_link_libraries( ) target_compile_definitions(parallel-overhead-locks PRIVATE USE_LOCKS=1) -if(ROCPROFSYS_INSTALL_EXAMPLES) - install( - TARGETS parallel-overhead parallel-overhead-locks - DESTINATION bin - COMPONENT rocprofiler-systems-examples - ) -endif() +set(PARALLEL_OVERHEAD_EXAMPLES parallel-overhead parallel-overhead-locks) +foreach(PARALLEL_OVERHEAD_EXAMPLE IN LISTS PARALLEL_OVERHEAD_EXAMPLES) + if(ROCPROFSYS_INSTALL_EXAMPLES AND TARGET ${PARALLEL_OVERHEAD_EXAMPLE}) + install( + TARGETS ${PARALLEL_OVERHEAD_EXAMPLE} + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples + COMPONENT rocprofiler-systems-examples + ) + endif() +endforeach() diff --git a/projects/rocprofiler-systems/examples/python/CMakeLists.txt b/projects/rocprofiler-systems/examples/python/CMakeLists.txt index 29b370b3ca..ab50d2f1cf 100644 --- a/projects/rocprofiler-systems/examples/python/CMakeLists.txt +++ b/projects/rocprofiler-systems/examples/python/CMakeLists.txt @@ -1,3 +1,6 @@ +# Copyright (c) Advanced Micro Devices, Inc. +# SPDX-License-Identifier: MIT + cmake_minimum_required(VERSION 3.21 FATAL_ERROR) project(rocprofiler-systems-python) @@ -36,7 +39,7 @@ if(Python3_FOUND) if(ROCPROFSYS_INSTALL_EXAMPLES) install( PROGRAMS ${PROJECT_BINARY_DIR}/${_FILE} - DESTINATION bin + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples COMPONENT rocprofiler-systems-examples ) endif() diff --git a/projects/rocprofiler-systems/examples/rccl/CMakeLists.txt b/projects/rocprofiler-systems/examples/rccl/CMakeLists.txt index 8fb842c1a4..1a23d69dd1 100644 --- a/projects/rocprofiler-systems/examples/rccl/CMakeLists.txt +++ b/projects/rocprofiler-systems/examples/rccl/CMakeLists.txt @@ -138,6 +138,14 @@ if(hip_FOUND AND rccl_FOUND) add_dependencies(rccl-tests::${_EXE_NAME} copy-${_EXE_NAME}) list(APPEND _RCCL_TEST_TARGETS "rccl-tests::${_EXE_NAME}") + + if(ROCPROFSYS_INSTALL_EXAMPLES) + install( + PROGRAMS ${_EXE_DEST_PATH} + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples + COMPONENT rocprofiler-systems-examples + ) + endif() endforeach() set(RCCL_TEST_TARGETS "${_RCCL_TEST_TARGETS}" CACHE INTERNAL "rccl-test targets") diff --git a/projects/rocprofiler-systems/examples/rewrite-caller/CMakeLists.txt b/projects/rocprofiler-systems/examples/rewrite-caller/CMakeLists.txt index aa1b7a0b34..1066d18e2a 100644 --- a/projects/rocprofiler-systems/examples/rewrite-caller/CMakeLists.txt +++ b/projects/rocprofiler-systems/examples/rewrite-caller/CMakeLists.txt @@ -1,3 +1,6 @@ +# Copyright (c) Advanced Micro Devices, Inc. +# SPDX-License-Identifier: MIT + cmake_minimum_required(VERSION 3.21 FATAL_ERROR) project(rocprofiler-systems-rewrite-caller-example LANGUAGES CXX) @@ -18,6 +21,10 @@ set(CMAKE_BUILD_TYPE "Debug") add_executable(rewrite-caller rewrite-caller.cpp) target_compile_options(rewrite-caller PRIVATE ${_FLAGS}) -if(ROCPROFSYS_INSTALL_EXAMPLES) - install(TARGETS rewrite-caller DESTINATION bin COMPONENT rocprofiler-systems-examples) +if(ROCPROFSYS_INSTALL_EXAMPLES AND TARGET rewrite-caller) + install( + TARGETS rewrite-caller + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples + COMPONENT rocprofiler-systems-examples + ) endif() diff --git a/projects/rocprofiler-systems/examples/roctx/CMakeLists.txt b/projects/rocprofiler-systems/examples/roctx/CMakeLists.txt index f5f7dd19c6..da58cdf4ac 100644 --- a/projects/rocprofiler-systems/examples/roctx/CMakeLists.txt +++ b/projects/rocprofiler-systems/examples/roctx/CMakeLists.txt @@ -1,24 +1,5 @@ -# MIT License -# -# Copyright (c) 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. +# Copyright (c) Advanced Micro Devices, Inc. +# SPDX-License-Identifier: MIT cmake_minimum_required(VERSION 3.21 FATAL_ERROR) @@ -113,6 +94,10 @@ if(NOT CMAKE_CXX_COMPILER_IS_HIPCC AND HIPCC_EXECUTABLE) rocprofiler_systems_custom_compilation(COMPILER ${HIPCC_EXECUTABLE} TARGET roctx) endif() -if(ROCPROFSYS_INSTALL_EXAMPLES) - install(TARGETS roctx DESTINATION bin COMPONENT rocprofiler-systems-examples) +if(ROCPROFSYS_INSTALL_EXAMPLES AND TARGET roctx) + install( + TARGETS roctx + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples + COMPONENT rocprofiler-systems-examples + ) endif() diff --git a/projects/rocprofiler-systems/examples/thread-limit/CMakeLists.txt b/projects/rocprofiler-systems/examples/thread-limit/CMakeLists.txt index 5a486228d8..63df5ca529 100644 --- a/projects/rocprofiler-systems/examples/thread-limit/CMakeLists.txt +++ b/projects/rocprofiler-systems/examples/thread-limit/CMakeLists.txt @@ -40,3 +40,11 @@ target_compile_options(tests-compile-options INTERFACE -g) add_executable(thread-limit thread-limit.cpp) target_compile_definitions(thread-limit PRIVATE MAX_THREADS=${ROCPROFSYS_MAX_THREADS}) target_link_libraries(thread-limit PRIVATE Threads::Threads tests-compile-options) + +if(ROCPROFSYS_INSTALL_EXAMPLES AND TARGET thread-limit) + install( + TARGETS thread-limit + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples + COMPONENT rocprofiler-systems-examples + ) +endif() diff --git a/projects/rocprofiler-systems/examples/trace-time-window/CMakeLists.txt b/projects/rocprofiler-systems/examples/trace-time-window/CMakeLists.txt index 3a8f396ba2..be61d05dc1 100644 --- a/projects/rocprofiler-systems/examples/trace-time-window/CMakeLists.txt +++ b/projects/rocprofiler-systems/examples/trace-time-window/CMakeLists.txt @@ -1,3 +1,6 @@ +# Copyright (c) Advanced Micro Devices, Inc. +# SPDX-License-Identifier: MIT + cmake_minimum_required(VERSION 3.21 FATAL_ERROR) project(rocprofiler-systems-trace-time-window-example LANGUAGES CXX) @@ -18,10 +21,10 @@ set(CMAKE_BUILD_TYPE "Debug") add_executable(trace-time-window trace-time-window.cpp) target_compile_options(trace-time-window PRIVATE ${_FLAGS}) -if(ROCPROFSYS_INSTALL_EXAMPLES) +if(ROCPROFSYS_INSTALL_EXAMPLES AND TARGET trace-time-window) install( TARGETS trace-time-window - DESTINATION bin + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples COMPONENT rocprofiler-systems-examples ) endif() diff --git a/projects/rocprofiler-systems/examples/transferBench/CMakeLists.txt b/projects/rocprofiler-systems/examples/transferBench/CMakeLists.txt index a0af07f3df..5d29d8f15b 100644 --- a/projects/rocprofiler-systems/examples/transferBench/CMakeLists.txt +++ b/projects/rocprofiler-systems/examples/transferBench/CMakeLists.txt @@ -1,3 +1,6 @@ +# Copyright (c) Advanced Micro Devices, Inc. +# SPDX-License-Identifier: MIT + cmake_minimum_required(VERSION 3.21 FATAL_ERROR) project(rocprofiler-systems-transferBench-example LANGUAGES CXX) @@ -120,6 +123,10 @@ if(NOT CMAKE_CXX_COMPILER_IS_HIPCC AND HIPCC_EXECUTABLE) rocprofiler_systems_custom_compilation(COMPILER ${HIPCC_EXECUTABLE} TARGET transferBench) endif() -if(ROCPROFSYS_INSTALL_EXAMPLES) - install(TARGETS transferBench DESTINATION bin COMPONENT rocprofiler-systems-examples) +if(ROCPROFSYS_INSTALL_EXAMPLES AND TARGET transferBench) + install( + TARGETS transferBench + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples + COMPONENT rocprofiler-systems-examples + ) endif() diff --git a/projects/rocprofiler-systems/examples/transpose/CMakeLists.txt b/projects/rocprofiler-systems/examples/transpose/CMakeLists.txt index 2406674764..0dcf2fd950 100644 --- a/projects/rocprofiler-systems/examples/transpose/CMakeLists.txt +++ b/projects/rocprofiler-systems/examples/transpose/CMakeLists.txt @@ -1,3 +1,6 @@ +# Copyright (c) Advanced Micro Devices, Inc. +# SPDX-License-Identifier: MIT + cmake_minimum_required(VERSION 3.21 FATAL_ERROR) project(rocprofiler-systems-transpose-example LANGUAGES CXX) @@ -93,6 +96,10 @@ if(NOT CMAKE_CXX_COMPILER_IS_HIPCC AND HIPCC_EXECUTABLE) rocprofiler_systems_custom_compilation(COMPILER ${HIPCC_EXECUTABLE} TARGET transpose) endif() -if(ROCPROFSYS_INSTALL_EXAMPLES) - install(TARGETS transpose DESTINATION bin COMPONENT rocprofiler-systems-examples) +if(ROCPROFSYS_INSTALL_EXAMPLES AND TARGET transpose) + install( + TARGETS transpose + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples + COMPONENT rocprofiler-systems-examples + ) endif() diff --git a/projects/rocprofiler-systems/examples/user-api/CMakeLists.txt b/projects/rocprofiler-systems/examples/user-api/CMakeLists.txt index cf99ae647c..4fcd7fb3e6 100644 --- a/projects/rocprofiler-systems/examples/user-api/CMakeLists.txt +++ b/projects/rocprofiler-systems/examples/user-api/CMakeLists.txt @@ -1,3 +1,6 @@ +# Copyright (c) Advanced Micro Devices, Inc. +# SPDX-License-Identifier: MIT + cmake_minimum_required(VERSION 3.21 FATAL_ERROR) project(rocprofiler-systems-user-api-example LANGUAGES CXX) @@ -24,6 +27,10 @@ target_link_libraries( PRIVATE Threads::Threads rocprofiler-systems::rocprofiler-systems-user-library ) -if(ROCPROFSYS_INSTALL_EXAMPLES) - install(TARGETS user-api DESTINATION bin COMPONENT rocprofiler-systems-examples) +if(ROCPROFSYS_INSTALL_EXAMPLES AND TARGET user-api) + install( + TARGETS user-api + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples + COMPONENT rocprofiler-systems-examples + ) endif() diff --git a/projects/rocprofiler-systems/examples/videodecode/CMakeLists.txt b/projects/rocprofiler-systems/examples/videodecode/CMakeLists.txt index ace4a9a189..1bf1fadeb3 100644 --- a/projects/rocprofiler-systems/examples/videodecode/CMakeLists.txt +++ b/projects/rocprofiler-systems/examples/videodecode/CMakeLists.txt @@ -1,3 +1,6 @@ +# Copyright (c) Advanced Micro Devices, Inc. +# SPDX-License-Identifier: MIT + cmake_minimum_required(VERSION 3.21 FATAL_ERROR) project(rocprofiler-systems-videodecode-example LANGUAGES CXX) @@ -176,15 +179,15 @@ if(FFMPEG_FOUND AND rocdecode_FOUND) target_compile_definitions(videodecode PUBLIC USE_AVCODEC_GREATER_THAN_58_134=1) endif() - if(ROCPROFSYS_INSTALL_EXAMPLES) + if(ROCPROFSYS_INSTALL_EXAMPLES AND TARGET videodecode) install( TARGETS videodecode - DESTINATION bin + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples COMPONENT rocprofiler-systems-examples ) install( - FILES ${CMAKE_BINARY_DIR}/videos - DESTINATION share/rocprofiler-systems/tests/videos + DIRECTORY ${CMAKE_BINARY_DIR}/videos/ + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/rocprofiler-systems/examples/videos COMPONENT rocprofiler-systems-examples ) endif() From 7794ac9ac67cc481d51393e25f46013e02568ba4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Mestre?= Date: Fri, 16 Jan 2026 13:25:11 +0000 Subject: [PATCH 02/21] [hip-tests] Fix Float16 accuracy tests (#2178) Tests were relying on floats for calculating ulp values when validating the output. This is not correct given that the calculations are done using Float16. The fix is to update the test framework to use fp16 ulp instead. --- .../catch/hipTestMain/config/config_amd_linux | 8 -- .../catch/unit/math/half_precision_math.cc | 36 +++--- .../hip-tests/catch/unit/math/math_common.hh | 4 +- .../hip-tests/catch/unit/math/validators.hh | 122 +++++++++++++++++- 4 files changed, 142 insertions(+), 28 deletions(-) diff --git a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux index 5413570155..6a168deafe 100644 --- a/projects/hip-tests/catch/hipTestMain/config/config_amd_linux +++ b/projects/hip-tests/catch/hipTestMain/config/config_amd_linux @@ -138,14 +138,6 @@ "=== TODO ===", "Unit_Device_tgammaf_Accuracy_Limited_Positive", "=== TODO === fail on 100% test data", - "Unit_Device_hexp10_Accuracy_Positive", - "Unit_Device_h2exp10_Accuracy_Positive", - "Unit_Device_hexp2_Accuracy_Positive", - "Unit_Device_h2exp2_Accuracy_Positive", - "Unit_Device_hlog_Accuracy_Positive", - "Unit_Device_h2log_Accuracy_Positive", - "Unit_Device_hlog10_Accuracy_Positive", - "Unit_Device_h2log10_Accuracy_Positive", "Unit_Device___hfma2_Accuracy_Positive", #endif #if defined gfx90a || defined gfx942 || defined gfx950 diff --git a/projects/hip-tests/catch/unit/math/half_precision_math.cc b/projects/hip-tests/catch/unit/math/half_precision_math.cc index 4cfa766ffd..f599b59133 100644 --- a/projects/hip-tests/catch/unit/math/half_precision_math.cc +++ b/projects/hip-tests/catch/unit/math/half_precision_math.cc @@ -45,7 +45,7 @@ MATH_UNARY_HP_KERNEL_DEF(hcos); * - HIP_VERSION >= 5.2 */ MATH_UNARY_HP_TEST_DEF_IMPL(hcos, static_cast(std::cos), - ULPValidatorBuilderFactory(2)); + ULPValidatorBuilderFactory(1)); MATH_UNARY_HP_KERNEL_DEF(h2cos); @@ -63,7 +63,7 @@ MATH_UNARY_HP_KERNEL_DEF(h2cos); * - HIP_VERSION >= 5.2 */ MATH_UNARY_HP_TEST_DEF_IMPL(h2cos, static_cast(std::cos), - ULPValidatorBuilderFactory(2)); + ULPValidatorBuilderFactory(1)); MATH_UNARY_HP_KERNEL_DEF(hsin); @@ -82,7 +82,7 @@ MATH_UNARY_HP_KERNEL_DEF(hsin); * - HIP_VERSION >= 5.2 */ MATH_UNARY_HP_TEST_DEF_IMPL(hsin, static_cast(std::sin), - ULPValidatorBuilderFactory(2)); + ULPValidatorBuilderFactory(1)); MATH_UNARY_HP_KERNEL_DEF(h2sin); @@ -100,7 +100,7 @@ MATH_UNARY_HP_KERNEL_DEF(h2sin); * - HIP_VERSION >= 5.2 */ MATH_UNARY_HP_TEST_DEF_IMPL(h2sin, static_cast(std::sin), - ULPValidatorBuilderFactory(2)); + ULPValidatorBuilderFactory(1)); MATH_UNARY_HP_KERNEL_DEF(hexp); @@ -119,7 +119,7 @@ MATH_UNARY_HP_KERNEL_DEF(hexp); * - HIP_VERSION >= 5.2 */ MATH_UNARY_HP_TEST_DEF_IMPL(hexp, static_cast(std::exp), - ULPValidatorBuilderFactory(2)); + ULPValidatorBuilderFactory(1)); MATH_UNARY_HP_KERNEL_DEF(h2exp); @@ -137,7 +137,7 @@ MATH_UNARY_HP_KERNEL_DEF(h2exp); * - HIP_VERSION >= 5.2 */ MATH_UNARY_HP_TEST_DEF_IMPL(h2exp, static_cast(std::exp), - ULPValidatorBuilderFactory(2)); + ULPValidatorBuilderFactory(1)); MATH_UNARY_HP_KERNEL_DEF(hexp10); @@ -156,7 +156,7 @@ MATH_UNARY_HP_KERNEL_DEF(hexp10); * - HIP_VERSION >= 5.2 */ MATH_UNARY_HP_TEST_DEF_IMPL(hexp10, static_cast(exp10f), - ULPValidatorBuilderFactory(2)); + ULPValidatorBuilderFactory(1)); MATH_UNARY_HP_KERNEL_DEF(h2exp10); @@ -174,7 +174,7 @@ MATH_UNARY_HP_KERNEL_DEF(h2exp10); * - HIP_VERSION >= 5.2 */ MATH_UNARY_HP_TEST_DEF_IMPL(h2exp10, static_cast(exp10f), - ULPValidatorBuilderFactory(2)); + ULPValidatorBuilderFactory(1)); MATH_UNARY_HP_KERNEL_DEF(hexp2); @@ -193,7 +193,7 @@ MATH_UNARY_HP_KERNEL_DEF(hexp2); * - HIP_VERSION >= 5.2 */ MATH_UNARY_HP_TEST_DEF_IMPL(hexp2, static_cast(std::exp2), - ULPValidatorBuilderFactory(2)); + ULPValidatorBuilderFactory(1)); MATH_UNARY_HP_KERNEL_DEF(h2exp2); @@ -211,7 +211,7 @@ MATH_UNARY_HP_KERNEL_DEF(h2exp2); * - HIP_VERSION >= 5.2 */ MATH_UNARY_HP_TEST_DEF_IMPL(h2exp2, static_cast(std::exp2), - ULPValidatorBuilderFactory(2)); + ULPValidatorBuilderFactory(1)); MATH_UNARY_HP_KERNEL_DEF(hlog); @@ -230,7 +230,7 @@ MATH_UNARY_HP_KERNEL_DEF(hlog); * - HIP_VERSION >= 5.2 */ MATH_UNARY_HP_TEST_DEF_IMPL(hlog, static_cast(std::log), - ULPValidatorBuilderFactory(1)); + ULPValidatorBuilderFactory(1)); MATH_UNARY_HP_KERNEL_DEF(h2log); @@ -248,7 +248,7 @@ MATH_UNARY_HP_KERNEL_DEF(h2log); * - HIP_VERSION >= 5.2 */ MATH_UNARY_HP_TEST_DEF_IMPL(h2log, static_cast(std::log), - ULPValidatorBuilderFactory(1)); + ULPValidatorBuilderFactory(1)); MATH_UNARY_HP_KERNEL_DEF(hlog10); @@ -267,7 +267,7 @@ MATH_UNARY_HP_KERNEL_DEF(hlog10); * - HIP_VERSION >= 5.2 */ MATH_UNARY_HP_TEST_DEF_IMPL(hlog10, static_cast(std::log10), - ULPValidatorBuilderFactory(2)); + ULPValidatorBuilderFactory(1)); MATH_UNARY_HP_KERNEL_DEF(h2log10); @@ -285,7 +285,7 @@ MATH_UNARY_HP_KERNEL_DEF(h2log10); * - HIP_VERSION >= 5.2 */ MATH_UNARY_HP_TEST_DEF_IMPL(h2log10, static_cast(std::log10), - ULPValidatorBuilderFactory(2)); + ULPValidatorBuilderFactory(1)); MATH_UNARY_HP_KERNEL_DEF(hlog2); @@ -304,7 +304,7 @@ MATH_UNARY_HP_KERNEL_DEF(hlog2); * - HIP_VERSION >= 5.2 */ MATH_UNARY_HP_TEST_DEF_IMPL(hlog2, static_cast(std::log2), - ULPValidatorBuilderFactory(1)); + ULPValidatorBuilderFactory(1)); MATH_UNARY_HP_KERNEL_DEF(h2log2); @@ -322,7 +322,7 @@ MATH_UNARY_HP_KERNEL_DEF(h2log2); * - HIP_VERSION >= 5.2 */ MATH_UNARY_HP_TEST_DEF_IMPL(h2log2, static_cast(std::log2), - ULPValidatorBuilderFactory(1)); + ULPValidatorBuilderFactory(1)); MATH_UNARY_HP_KERNEL_DEF(hsqrt); @@ -341,7 +341,7 @@ MATH_UNARY_HP_KERNEL_DEF(hsqrt); * - HIP_VERSION >= 5.2 */ MATH_UNARY_HP_TEST_DEF_IMPL(hsqrt, static_cast(std::sqrt), - ULPValidatorBuilderFactory(1)); + ULPValidatorBuilderFactory(1)); MATH_UNARY_HP_KERNEL_DEF(h2sqrt); @@ -359,7 +359,7 @@ MATH_UNARY_HP_KERNEL_DEF(h2sqrt); * - HIP_VERSION >= 5.2 */ MATH_UNARY_HP_TEST_DEF_IMPL(h2sqrt, static_cast(std::sqrt), - ULPValidatorBuilderFactory(1)); + ULPValidatorBuilderFactory(1)); MATH_UNARY_HP_KERNEL_DEF(hceil); diff --git a/projects/hip-tests/catch/unit/math/math_common.hh b/projects/hip-tests/catch/unit/math/math_common.hh index 08bd720816..a92685210f 100644 --- a/projects/hip-tests/catch/unit/math/math_common.hh +++ b/projects/hip-tests/catch/unit/math/math_common.hh @@ -187,7 +187,9 @@ template class MathTest { std::stringstream ss; ss << "Input value(s): " << std::scientific << std::setprecision(std::numeric_limits::max_digits10 - 1); - ((ss << " " << args), ...) << "\n" << actual_val << " "; + ((ss << " " << args), ...) << "\n" + << "Output value: " << actual_val << "\n" + << "Condition failed: "; return ss.str(); } diff --git a/projects/hip-tests/catch/unit/math/validators.hh b/projects/hip-tests/catch/unit/math/validators.hh index 67c49132d4..d62ec5381b 100644 --- a/projects/hip-tests/catch/unit/math/validators.hh +++ b/projects/hip-tests/catch/unit/math/validators.hh @@ -25,6 +25,12 @@ THE SOFTWARE. #include #include +#include +#include +#include + +#include "Float16.hh" + // Define a new MatcherBase class with a public 'describe' member function because // Catch::MatcherBase::describe is protected and thus can't be used via a pointer to // Catch::MatcherBase. @@ -61,6 +67,113 @@ template class ValidatorBase : public MatcherBase bool nan = false; }; +struct Float16WithinUlpsMatcher : MatcherBase { + Float16WithinUlpsMatcher(Float16 target, uint64_t ulps) : m_target(target), m_ulps(ulps) {} + + bool match(Float16 const& matchee) const override { + // Comparison with NaN should always be false. + // This way we can rule it out before getting into the ugly details + if (__hisnan(matchee) || __hisnan(m_target)) { + return false; + } + + auto value_bits = convertFloat16toInt16(matchee); + auto target_bits = convertFloat16toInt16(m_target); + + // If signs differ, handle the special +0 vs -0 case explicitly. + if ((value_bits < 0) != (target_bits < 0)) { + return matchee == m_target; + } + + auto ulp_diff = std::abs(value_bits - target_bits); + return static_cast(ulp_diff) <= m_ulps; + } + + std::string describe() const override { + std::stringstream ret; + + ret << "is within " << m_ulps << " ULPs of "; + + write(ret, m_target); + ret << 'f'; + ret << " (["; + + write(ret, step(m_target, -FLOAT16_MAX, m_ulps)); + ret << ", "; + write(ret, step(m_target, FLOAT16_MAX, m_ulps)); + + ret << "])"; + + return ret.str(); + } + + private: + Float16 getNextAfter(Float16 from, Float16 direction) const { + constexpr int16_t signbit_float16 = 0x8000; + + // Encode inputs as 16-bit integers + const int16_t from_bits = convertFloat16toInt16(from); + const int16_t direction_bits = convertFloat16toInt16(direction); + + // Special cases + if (from_bits == direction_bits) return direction_bits; + if (std::abs(from_bits) == static_cast(0) && + std::abs(direction_bits) == static_cast(0)) + return direction; + + // Makes integer comparisons reflect numeric ordering across sign. + const int16_t from_ordered = (from_bits < 0) ? signbit_float16 - from_bits : from_bits; + const int16_t direction_ordered = + (direction_bits < 0) ? signbit_float16 - direction_bits : direction_bits; + + // Decide whether to move up or down by one ULP + const int16_t step = (from_ordered < direction_ordered) ? 1 : -1; + + // Take one step + const int16_t after_step_ordered = from_ordered + step; + + // Map back from ordered space to raw Float16 bits. + int16_t next_bits = + (after_step_ordered < 0) ? signbit_float16 - after_step_ordered : after_step_ordered; + + // Handle boundary behavior for the most-negative edge case. + if (from_ordered == -1 && (from_ordered < direction_ordered)) { + next_bits = signbit_float16; + } + + return convertInt16toFloat16(next_bits); + } + + Float16 step(Float16 start, Float16 direction, uint64_t steps) const { + Float16 result = start; + for (uint64_t i = 0; i < steps; ++i) { + result = getNextAfter(result, direction); + } + return result; + } + + void write(std::ostream& out, Float16 num) const { + const uint32_t float16_max_digits = 5; + out << std::scientific << std::setprecision(float16_max_digits) << num; + } + + static Float16 convertInt16toFloat16(int16_t d) { + Float16 i; + std::memcpy(&i, &d, sizeof(int16_t)); + return i; + } + + static int16_t convertFloat16toInt16(Float16 d) { + uint16_t i; + std::memcpy(&i, &d, sizeof(Float16)); + return i; + } + + Float16 m_target; + uint64_t m_ulps; +}; + + template auto ULPValidatorBuilderFactory(int64_t ulps) { return [=](T target, auto&&...) { return std::make_unique>( @@ -68,6 +181,13 @@ template auto ULPValidatorBuilderFactory(int64_t ulps) { }; }; +template <> inline auto ULPValidatorBuilderFactory(int64_t ulps) { + return [=](Float16 target, auto&&...) { + return std::make_unique>( + target, Float16WithinUlpsMatcher(target, ulps)); + }; +}; + template auto AbsValidatorBuilderFactory(double margin) { return [=](T target, auto&&...) { return std::make_unique>( @@ -96,7 +216,7 @@ template class EqValidator : public MatcherBase { std::string describe() const override { std::stringstream ss; - ss << " is not equal to " << target_; + ss << "is equal to " << target_; return ss.str(); } From e6236417f734b508bcccecfbf468f916207a0e8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Mestre?= Date: Fri, 16 Jan 2026 15:02:48 +0000 Subject: [PATCH 03/21] SWDEV-571222 - Fix bf16 headers on gcc (#2260) GCC does not support anonymous structs with members that have non-trivial constructors. This commit changes the header to remove the union when compiling with gcc. This should be a non-breaking change for other compilers. --- .../include/hip/amd_detail/amd_hip_bf16.h | 39 ++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/projects/clr/hipamd/include/hip/amd_detail/amd_hip_bf16.h b/projects/clr/hipamd/include/hip/amd_detail/amd_hip_bf16.h index 132abf713d..8d07119f27 100644 --- a/projects/clr/hipamd/include/hip/amd_detail/amd_hip_bf16.h +++ b/projects/clr/hipamd/include/hip/amd_detail/amd_hip_bf16.h @@ -111,9 +111,8 @@ #if !defined(__HIPCC_RTC__) #include #include "amd_hip_vector_types.h" // float2 etc -#include "device_library_decls.h" // ocml conversion functions -#include "math_fwd.h" // ocml device functions #if defined(__clang__) && defined(__HIP__) +#include "math_fwd.h" // ocml device functions #include // define warpSize #include // Sync functions #endif @@ -338,7 +337,11 @@ struct __attribute__((aligned(2))) __hip_bfloat16 { }; /**@}*/ +#if defined(__clang__) typedef __bf16 __bf16_2 __attribute__((ext_vector_type(2))); +#else +typedef __bf16 __bf16_2 __attribute__((vector_size(sizeof(__bf16) * 2))); +#endif /** * \defgroup HIP_INTRINSIC_BFLOAT162_STRUCT @@ -350,6 +353,7 @@ struct __attribute__((aligned(4))) __hip_bfloat162 { static_assert(sizeof(__hip_bfloat16[2]) == sizeof(__bf16_2)); public: +#if defined(__clang__) union { struct { __hip_bfloat16 x; /*! \brief raw representation of bfloat16 */ @@ -357,7 +361,12 @@ struct __attribute__((aligned(4))) __hip_bfloat162 { }; __bf16_2 __xy_bf162; }; - +#else + /* GCC does not support anonymous structs with members that have non-trivial constructors (Clang + allows this as an extension). Expose x and y directly instead. */ + __hip_bfloat16 x; + __hip_bfloat16 y; +#endif public: /*! \brief create __hip_bfloat162 from __hip_bfloat162_raw */ @@ -373,7 +382,11 @@ struct __attribute__((aligned(4))) __hip_bfloat162 { : x(a), y(b) {} /*! \brief create __hip_bfloat162 from vector of __bf16_2 */ +#if defined(__clang__) __BF16_HOST_DEVICE__ __hip_bfloat162(const __bf16_2 in) : __xy_bf162(in) {} +#else + __BF16_HOST_DEVICE__ __hip_bfloat162(const __bf16_2 in) : x{in[0]}, y{in[1]} {} +#endif /*! \brief default constructor of __hip_bfloat162 */ __BF16_HOST_DEVICE__ __hip_bfloat162() = default; @@ -392,11 +405,22 @@ struct __attribute__((aligned(4))) __hip_bfloat162 { } /*! \brief return a vector of bf16 */ - __BF16_HOST_DEVICE__ operator __bf16_2() const { return __xy_bf162; } + __BF16_HOST_DEVICE__ operator __bf16_2() const { +#if defined(__clang__) + return __xy_bf162; +#else + return __bf16_2{x, y}; +#endif + } /*! \brief return a vector of bf16 */ __BF16_HOST_DEVICE__ __hip_bfloat162& operator=(const __bf16_2 in) { +#if defined(__clang__) __xy_bf162 = in; +#else + x = __hip_bfloat16{in[0]}; + y = __hip_bfloat16{in[1]}; +#endif return *this; } @@ -835,6 +859,7 @@ __BF16_HOST_DEVICE_STATIC__ __hip_bfloat16 __hdiv(const __hip_bfloat16 a, const return (__bf16)a / (__bf16)b; } +#if defined(__clang__) && defined(__HIP__) /** * \ingroup HIP_INTRINSIC_BFLOAT16_ARITH * \brief Performs FMA of given bfloat16 values @@ -844,6 +869,7 @@ __BF16_DEVICE_STATIC__ __hip_bfloat16 __hfma(const __hip_bfloat16 a, const __hip return __hip_bfloat16(__builtin_elementwise_fma(__bf16(a), __bf16(b), __bf16(c))); ; } +#endif /** * \ingroup HIP_INTRINSIC_BFLOAT16_ARITH @@ -919,6 +945,8 @@ __BF16_HOST_DEVICE_STATIC__ __hip_bfloat162 __hadd2_rn(const __hip_bfloat162 a, return __hip_bfloat162{__bf16_2(a) + __bf16_2(b)}; } + +#if defined(__clang__) && defined(__HIP__) /** * \ingroup HIP_INTRINSIC_BFLOAT162_ARITH * \brief Performs FMA of given bfloat162 values @@ -927,6 +955,7 @@ __BF16_DEVICE_STATIC__ __hip_bfloat162 __hfma2(const __hip_bfloat162 a, const __ const __hip_bfloat162 c) { return __hip_bfloat162{__builtin_elementwise_fma(__bf16_2(a), __bf16_2(b), __bf16_2(c))}; } +#endif /** * \ingroup HIP_INTRINSIC_BFLOAT162_ARITH @@ -1639,6 +1668,7 @@ __BF16_HOST_DEVICE_STATIC__ bool operator>=(const __hip_bfloat162& l, const __hi return fl.x >= fr.x && fl.x >= fr.y; } +#if defined(__clang__) && defined(__HIP__) /** * \ingroup HIP_INTRINSIC_BFLOAT16_MATH * \brief Calculate ceil of bfloat16 @@ -1883,7 +1913,6 @@ __BF16_DEVICE_STATIC__ __hip_bfloat162 h2trunc(const __hip_bfloat162 h) { return __hip_bfloat162(htrunc(h.x), htrunc(h.y)); } -#if defined(__clang__) && defined(__HIP__) /** * \ingroup HIP_INTRINSIC_BFLOAT162_MATH * \brief Atomic add bfloat162 From f64d8e0f438735cb59ad85d5c6a885a92ea81641 Mon Sep 17 00:00:00 2001 From: vedithal-amd Date: Fri, 16 Jan 2026 10:36:19 -0500 Subject: [PATCH 04/21] [rocprofiler-compute] Improve native tool discovery and partition detection (#2630) * Improve native tool discovery and partition detection - Enhanced native tool path resolution to support CMAKE_INSTALL_LIBDIR variations (lib, lib64, lib32, etc.) using glob pattern matching - Extracted path variables to avoid duplication in error messages - Improved error message clarity by showing exact paths searched for .so and .cpp files - Simplified code path construction using consistent Path.resolve().parents[x] syntax - Fixed redundant partition warnings on pre-MI300 GPUs by adding architecture check - Only query compute/memory partition on MI300+ series (gfx940+) - Added proper type hints for gpu_arch parameter - Moved gpu_info extraction after soc_info to ensure gpu_arch is available - Improved code comments for MI300 series threshold * Handle gpu arch like a hex string --- projects/rocprofiler-compute/CHANGELOG.md | 2 + .../rocprof_compute_profile/profiler_base.py | 30 +++++++++----- .../rocprofiler-compute/src/utils/specs.py | 40 +++++++++++++------ 3 files changed, 50 insertions(+), 22 deletions(-) diff --git a/projects/rocprofiler-compute/CHANGELOG.md b/projects/rocprofiler-compute/CHANGELOG.md index 5b4c63c36a..d541344ae7 100644 --- a/projects/rocprofiler-compute/CHANGELOG.md +++ b/projects/rocprofiler-compute/CHANGELOG.md @@ -49,6 +49,8 @@ Full documentation for ROCm Compute Profiler is available at [https://rocm.docs. * Fix issue where counter collection data was empty when profiling workload which spawn multiple child processes +* Fix redundant warnings for compute/memory partition not found for < MI 300 series GPUs by skipping partition checks + ### Removed * Removed "VL1 Lat" metric for AMD Instinct MI300 series GPUs, due to MI300 series not supporting TCP_TCP_LATENCY_sum counter. diff --git a/projects/rocprofiler-compute/src/rocprof_compute_profile/profiler_base.py b/projects/rocprofiler-compute/src/rocprof_compute_profile/profiler_base.py index 9bae23bf14..a79d188c75 100644 --- a/projects/rocprofiler-compute/src/rocprof_compute_profile/profiler_base.py +++ b/projects/rocprofiler-compute/src/rocprof_compute_profile/profiler_base.py @@ -531,12 +531,15 @@ class RocProfCompute_Base: and not args.attach_pid ): # Use native counter collection tool + # Use lib* glob pattern to handle CMAKE_INSTALL_LIBDIR variations + # (lib, lib64, lib32, etc. depending on distribution) + native_tool_base_path = Path(sys.argv[0]).resolve().parents[2] + native_tool_glob_pattern = ( + "lib*/rocprofiler-compute/librocprofiler-compute-tool.so" + ) try: native_tool_path = str( - Path(sys.argv[0]).resolve().parents[2] - / "lib" - / "rocprofiler-compute" - / "librocprofiler-compute-tool.so" + next(native_tool_base_path.glob(native_tool_glob_pattern)) ) except Exception as e: console_debug( @@ -552,6 +555,7 @@ class RocProfCompute_Base: ) / "librocprofiler-compute-tool.so" ) + native_tool_cpp_path = Path(__file__).resolve().parents[1] / "lib" link_libraries = ("rocprofiler-sdk",) build_command = ( # Create shared object @@ -564,10 +568,10 @@ class RocProfCompute_Base: # rocprofiler sdk library path f"-L {str(Path(args.rocprofiler_sdk_tool_path).parent.parent)} " # native tool source files (tool.cpp and helper.cpp) - f"{str(Path(__file__).parent.parent)}/" - "lib/rocprofiler_compute_tool.cpp " - f"{str(Path(__file__).parent.parent)}/" - "lib/helper.cpp " + f"{native_tool_cpp_path}/" + "rocprofiler_compute_tool.cpp " + f"{native_tool_cpp_path}/" + "helper.cpp " # temporary shared object for native tool f"-o {native_tool_path}" ) @@ -575,7 +579,15 @@ class RocProfCompute_Base: success, output = capture_subprocess_output(shlex.split(build_command)) console_debug(f"Build output: {output}") if not success: - console_error("Failed to build native counter collection tool.") + console_error( + "Failed to use native counter collection tool.\n" + "Could not find pre-built .so file at: " + f"{native_tool_base_path / native_tool_glob_pattern}\n" + "Could not find source .cpp files in folder: " + f"{native_tool_cpp_path}\n" + "Please ensure the native tool library is installed " + "or source files are present." + ) if self.__profiler == "rocprofiler-sdk": options = self.get_profiler_options(native_tool_path=native_tool_path) diff --git a/projects/rocprofiler-compute/src/utils/specs.py b/projects/rocprofiler-compute/src/utils/specs.py index b9202deb73..e55335686f 100644 --- a/projects/rocprofiler-compute/src/utils/specs.py +++ b/projects/rocprofiler-compute/src/utils/specs.py @@ -174,15 +174,15 @@ def generate_machine_specs( ########################################## machine_info = extract_machine_info() - # FIXME: use device - # Load amd-smi data - gpu_info = extract_gpu_info() - ########################################## ## B. SoC Specs ########################################## soc_info = extract_soc_info() + # FIXME: use device + # Load amd-smi data + gpu_info = extract_gpu_info(gpu_arch=soc_info["gpu_arch"]) + # Combine all specifications with amdsmi_ctx(): specs = MachineSpecs( @@ -269,7 +269,16 @@ def extract_machine_info() -> dict[str, Any]: @demarcate -def extract_gpu_info() -> dict[str, Any]: +def extract_gpu_info(gpu_arch: Optional[str]) -> dict[str, Any]: + # Partition is only supported on >= MI 300 series + # (gpu_arch should be gfx940 or higher for MI300+) + is_partition_supported = False + if gpu_arch and gpu_arch.startswith("gfx") and len(gpu_arch) >= 6: + try: + is_partition_supported = int(gpu_arch[3:6], 16) >= 0x940 + except ValueError: + pass # Invalid hex string, keep is_partition_supported as False + result: dict[str, Optional[str]] = { "vbios": None, "compute_partition": None, @@ -278,17 +287,22 @@ def extract_gpu_info() -> dict[str, Any]: with amdsmi_ctx(): result["vbios"] = get_gpu_vbios_part_number() - result["compute_partition"] = get_gpu_compute_partition() - result["memory_partition"] = get_gpu_memory_partition() + if is_partition_supported: + result["compute_partition"] = get_gpu_compute_partition() + result["memory_partition"] = get_gpu_memory_partition() + else: + result["compute_partition"] = "N/A" + result["memory_partition"] = "N/A" # Apply defaults and warnings - if result["compute_partition"] == "N/A" or not result["compute_partition"]: - console_warning("Cannot detect accelerator partition from amd-smi.") - console_warning("Applying default accelerator partition: SPX") - result["compute_partition"] = "SPX" + if is_partition_supported: + if result["compute_partition"] == "N/A" or not result["compute_partition"]: + console_warning("Cannot detect accelerator partition from amd-smi.") + console_warning("Applying default accelerator partition: SPX") + result["compute_partition"] = "SPX" - if result["memory_partition"] == "N/A" or not result["memory_partition"]: - console_warning("Cannot detect memory partition from amd-smi.") + if result["memory_partition"] == "N/A" or not result["memory_partition"]: + console_warning("Cannot detect memory partition from amd-smi.") console_debug( f"vbios is {result['vbios']}, compute partition is " From 249a947dc75b646f1630b4595de00fac0a687414 Mon Sep 17 00:00:00 2001 From: Rahul Manocha <153310294+manocharahul@users.noreply.github.com> Date: Fri, 16 Jan 2026 08:34:21 -0800 Subject: [PATCH 05/21] Fix set/get access failure for VMM on windows (#2280) * Fix set/get access failure for VMM on windows * seperate code paths for linux and windows to avoid using import/export calls in windows --------- Co-authored-by: Rahul Manocha --- .../hsa-runtime/core/runtime/runtime.cpp | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/runtime.cpp b/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/runtime.cpp index d23f889637..4fbf5aa145 100644 --- a/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/runtime.cpp +++ b/projects/rocr-runtime/runtime/hsa-runtime/core/runtime/runtime.cpp @@ -3666,32 +3666,30 @@ hsa_status_t Runtime::VMemoryHandleMap(void* va, size_t size, size_t in_offset, // Create handle by exporting and importing the memory from the owning agent auto &agent_driver = agent->driver(); + ShareableHandle shareable_handle; +#if defined(__linux__) hsa_status_t status = agent_driver.ExportDMABuf(memoryHandleIt->first, size, &dmabuf_fd, &offset); if (status != HSA_STATUS_SUCCESS) return status; assert(offset == 0); - ShareableHandle shareable_handle; status = agent_driver.ImportDMABuf(dmabuf_fd, *agent, shareable_handle); if (status != HSA_STATUS_SUCCESS) return status; - if (dmabuf_fd != -1) { - close(dmabuf_fd); - } + close(dmabuf_fd); // Get address that memory is mapped to - if (shareable_handle.IsValid()) { - ret = GetAmdgpuDeviceArgs(agent, shareable_handle, &drm_fd, &drm_cpu_addr); - if (ret) return HSA_STATUS_ERROR; - } else { - hsa_status_t status = agent_driver.GetShareableHandle(va, memoryHandleIt->first, size, &shareable_handle); - if (status != HSA_STATUS_SUCCESS) { - return status; - } - drm_cpu_addr = reinterpret_cast(va); + ret = GetAmdgpuDeviceArgs(agent, shareable_handle, &drm_fd, &drm_cpu_addr); + if (ret) return HSA_STATUS_ERROR; +#else + hsa_status_t status = agent_driver.GetShareableHandle(va, memoryHandleIt->first, size, &shareable_handle); + if (status != HSA_STATUS_SUCCESS) { + return status; } + drm_cpu_addr = reinterpret_cast(va); +#endif mapped_handle_map_.emplace( std::piecewise_construct, std::forward_as_tuple(va), @@ -3783,6 +3781,7 @@ Runtime::MappedHandleAllowedAgent::MappedHandleAllowedAgent( uint64_t offset = 0; MemoryHandle *memHandle = mappedHandle->mem_handle; +#if defined(__linux__) // Export memory from owner agent. hsa_status_t status = memHandle->agentOwner()->driver().ExportDMABuf( memHandle->thunk_handle, mappedHandle->size, &dmabuf_fd, &offset); @@ -3798,6 +3797,9 @@ Runtime::MappedHandleAllowedAgent::MappedHandleAllowedAgent( close(dmabuf_fd); if (status != HSA_STATUS_SUCCESS) return; +#else + shareable_handle.handle = _mappedHandle->shareable_handle.handle; +#endif } Runtime::MappedHandleAllowedAgent::~MappedHandleAllowedAgent() { From 005f07004deddcd3837606588f71f0119347bd50 Mon Sep 17 00:00:00 2001 From: cfallows-amd Date: Fri, 16 Jan 2026 12:48:19 -0500 Subject: [PATCH 06/21] [rocprofiler-compute] Update README (#2589) * Update readme general section and citation version and date. Signed-off-by: Carrie Fallows * Minor change to project title- changing now to not forget but we are waiti8ng on feedback about citation from r&d. Signed-off-by: Carrie Fallows * Edit citation from R&D feedback --------- Signed-off-by: Carrie Fallows --- projects/rocprofiler-compute/README.md | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/projects/rocprofiler-compute/README.md b/projects/rocprofiler-compute/README.md index 89e3f105b9..b7ed73b217 100644 --- a/projects/rocprofiler-compute/README.md +++ b/projects/rocprofiler-compute/README.md @@ -4,14 +4,13 @@ ROCm Compute Profiler is a system performance profiling tool for machine learning/HPC workloads running on AMD MI GPUs. The tool presently -targets usage on MI100, MI200, and MI300 accelerators. +targets usage on MI100, MI200, MI300, and MI350 series accelerators. * For more information on available features, installation steps, and workload profiling and analysis, please refer to the online [documentation](https://rocm.docs.amd.com/projects/rocprofiler-compute/en/latest/). -* ROCm Compute Profiler is an AMD open source research project and is not supported -as part of the ROCm software stack. We welcome contributions and +* ROCm Compute Profiler is an AMD open source tool that is part of the ROCm software stack. We welcome contributions and feedback from the community. Please see the [CONTRIBUTING.md](CONTRIBUTING.md) file for additional details on our contribution process. @@ -115,7 +114,7 @@ This software can be cited using a Zenodo style reference is provided below for convenience: ``` -@software{xiaomin_lu_2022_7314631 +@misc{xiaomin_lu_2022_7314631 author = {Xiaomin Lu and Cole Ramos and Fei Zheng and @@ -124,12 +123,7 @@ style reference is provided below for convenience: Keith Lowery and Nicholas Curtis and Cristian Di Pietrantonio}, - title = {ROCm/rocprofiler-compute: v3.1.0 (12 February 2025)}, - month = February, - year = 2025, - publisher = {Zenodo}, - version = {v3.1.0}, - doi = {10.5281/zenodo.7314631}, - url = {https://doi.org/10.5281/zenodo.7314631} + title = {rocprofiler-compute}, + url = {https://github.com/ROCm/rocm-systems/blob/develop/projects/rocprofiler-compute} } ``` From b53c99669c7cc442ae75aaf7e782f7dc19370139 Mon Sep 17 00:00:00 2001 From: habajpai-amd Date: Sat, 17 Jan 2026 02:38:52 +0530 Subject: [PATCH 07/21] Revert "fix: prevent double-free crash during process exit in amd-smi (#2213)" (#2640) This reverts commit 7b00d3a89b43bdd084454843db0c8412f44414dd. The workaround is no longer needed - root cause fixed in: - rocm-smi-lib (PR #2531): Made devInfoTypesStrings file-local static - amdsmi (PR #2575): Added visibility("hidden") attribute --- .../source/lib/core/gpu.cpp | 16 ++----------- .../lib/rocprof-sys/library/amd_smi.cpp | 5 +++- .../library/components/exit_gotcha.cpp | 23 +------------------ 3 files changed, 7 insertions(+), 37 deletions(-) diff --git a/projects/rocprofiler-systems/source/lib/core/gpu.cpp b/projects/rocprofiler-systems/source/lib/core/gpu.cpp index fdfd70348d..08cab7fb55 100644 --- a/projects/rocprofiler-systems/source/lib/core/gpu.cpp +++ b/projects/rocprofiler-systems/source/lib/core/gpu.cpp @@ -31,6 +31,8 @@ } \ } // namespace ::tim::cereal +#include "common/defines.h" + #if !defined(ROCPROFSYS_USE_ROCM) # define ROCPROFSYS_USE_ROCM 0 #endif @@ -40,7 +42,6 @@ #include -#include #include #include "core/agent_manager.hpp" @@ -92,17 +93,6 @@ _amdsmi_is_initialized() return initialized; } -void -prevent_amdsmi_library_unload() -{ - static bool _initialized = false; - if(_initialized) return; - _initialized = true; - - dlopen("libamd_smi.so", RTLD_NOW | RTLD_NOLOAD | RTLD_NODELETE); - dlopen("librocm_smi64.so", RTLD_NOW | RTLD_NOLOAD | RTLD_NODELETE); -} - bool amdsmi_init() { @@ -113,8 +103,6 @@ amdsmi_init() ROCPROFSYS_AMD_SMI_CALL(::amdsmi_init(AMDSMI_INIT_AMD_GPUS)); get_processor_handles(); _amdsmi_is_initialized() = true; // Mark as initialized - - prevent_amdsmi_library_unload(); } catch(std::exception& _e) { LOG_ERROR("Exception thrown initializing amd-smi: {}", _e.what()); diff --git a/projects/rocprofiler-systems/source/lib/rocprof-sys/library/amd_smi.cpp b/projects/rocprofiler-systems/source/lib/rocprof-sys/library/amd_smi.cpp index 136487ecd0..da38dfe77b 100644 --- a/projects/rocprofiler-systems/source/lib/rocprof-sys/library/amd_smi.cpp +++ b/projects/rocprofiler-systems/source/lib/rocprof-sys/library/amd_smi.cpp @@ -1272,7 +1272,10 @@ shutdown() try { - data::shutdown(); + if(data::shutdown()) + { + ROCPROFSYS_AMD_SMI_CALL(amdsmi_shut_down()); + } } catch(std::runtime_error& _e) { LOG_WARNING("Exception thrown when shutting down amd-smi: {}", _e.what()); diff --git a/projects/rocprofiler-systems/source/lib/rocprof-sys/library/components/exit_gotcha.cpp b/projects/rocprofiler-systems/source/lib/rocprof-sys/library/components/exit_gotcha.cpp index d1dd92a664..ce8654f206 100644 --- a/projects/rocprofiler-systems/source/lib/rocprof-sys/library/components/exit_gotcha.cpp +++ b/projects/rocprofiler-systems/source/lib/rocprof-sys/library/components/exit_gotcha.cpp @@ -24,6 +24,7 @@ #include "core/common.hpp" #include "core/config.hpp" #include "core/state.hpp" +#include "core/timemory.hpp" #include "library/runtime.hpp" #include @@ -33,9 +34,7 @@ #include "logger/debug.hpp" #include -#include #include -#include namespace rocprofsys { @@ -89,26 +88,6 @@ void exit_gotcha::operator()(const gotcha_data& _data, exit_func_t _func, int _ec) const { _exit_info = { true, _data.tool_id.find("quick") != std::string::npos, _ec }; - - if(config::get_use_amd_smi()) - { - threading::clear_callbacks(); - - if(get_state() < ::rocprofsys::State::Finalized && !is_child_process()) - { - LOG_DEBUG("Finalizing {} before calling {}({})...", get_exe_name(), - _data.tool_id, _ec); - - rocprofsys_finalize(); - } - - LOG_DEBUG("Calling _exit({}) in {} to avoid AMD SMI cleanup issues...", _ec, - get_exe_name().c_str()); - - std::fflush(nullptr); - _exit(_ec); - } - invoke_exit_gotcha(_data, _func, _ec); } From 1ac805cb35061ec1fa30e89c754fbdab14c91899 Mon Sep 17 00:00:00 2001 From: Gopesh Bhardwaj Date: Sat, 17 Jan 2026 14:55:55 +0530 Subject: [PATCH 08/21] [rocprofiler-sdk][Documentation] Updating CHANGELOG for 7.2 (#2573) * Updating CHANGELOG for 7.2 * Updated CHANGELOG * Addressed feedback * Addressed Feedback * Updated based on review comments * Update installation steps and documentation links Updated installation documentation and links to latest repository. * Addressed Feedback * Updated CHANGELOG * Addressed feedback * updated CHANGELOG * Apply suggestion from @prbasyal-amd Co-authored-by: Pratik Basyal --------- Co-authored-by: Swati Rawat <120587655+SwRaw@users.noreply.github.com> Co-authored-by: Pratik Basyal --- projects/rocprofiler-sdk/CHANGELOG.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/projects/rocprofiler-sdk/CHANGELOG.md b/projects/rocprofiler-sdk/CHANGELOG.md index 59a41f593b..c128e1ed80 100644 --- a/projects/rocprofiler-sdk/CHANGELOG.md +++ b/projects/rocprofiler-sdk/CHANGELOG.md @@ -242,6 +242,19 @@ Full documentation for ROCprofiler-SDK is available at [rocm.docs.amd.com/projec ## ROCprofiler-SDK 1.1.0 for ROCm release 7.2 ### Added -- Strix halo support for counter collection. +- Counter collection support for `gfx1150` and `gfx1151` (Strix Halo). +- HSA Extension API v8 support. +- `hipStreamCopyAttributes` API implementation. +### Optimized +- Improved process attachment and updated the corresponding [documentation](https://rocm.docs.amd.com/projects/rocprofiler-sdk/en/latest/how-to/using-rocprofv3-process-attachment.html). +- Improved [Quick reference guide for rocprofv3] (https://rocm.docs.amd.com/projects/rocprofiler-sdk/en/latest/quick_guide.html). +- Updated installation documentation with links to the latest repository (https://rocm.docs.amd.com/projects/rocprofiler-sdk/en/latest/install/installation.html). + +### Resolved issues +- Fixed multi-GPU dimension mismatch. +- Fixed device lock issue for dispatch counters. +- Addressed OpenMP Tools task scheduling null pointer exception. +- Fixed stream ID errors arising during process attachment. +- Fixed issues arising during dynamic code object loading. From e49b501e9aa09d7e6a4413687e85f2bf5b21902a Mon Sep 17 00:00:00 2001 From: lloginov-amd Date: Mon, 19 Jan 2026 16:24:30 +0100 Subject: [PATCH 09/21] Add scratch memory support (#2211) --- .../source/lib/core/rocprofiler-sdk.cpp | 3 +- .../lib/core/trace_cache/cache_manager.hpp | 2 +- .../core/trace_cache/perfetto_processor.cpp | 66 ++++++++ .../core/trace_cache/perfetto_processor.hpp | 1 + .../lib/core/trace_cache/rocpd_processor.cpp | 120 +++++++++----- .../lib/core/trace_cache/rocpd_processor.hpp | 1 + .../lib/core/trace_cache/sample_processor.hpp | 18 +++ .../lib/core/trace_cache/sample_type.hpp | 78 +++++++++ .../rocprof-sys/library/rocprofiler-sdk.cpp | 152 +++++++++++++++++- .../library/rocprofiler-sdk/fwd.hpp | 12 +- 10 files changed, 398 insertions(+), 55 deletions(-) diff --git a/projects/rocprofiler-systems/source/lib/core/rocprofiler-sdk.cpp b/projects/rocprofiler-systems/source/lib/core/rocprofiler-sdk.cpp index 52b9f2607e..a0df719742 100644 --- a/projects/rocprofiler-systems/source/lib/core/rocprofiler-sdk.cpp +++ b/projects/rocprofiler-systems/source/lib/core/rocprofiler-sdk.cpp @@ -367,7 +367,6 @@ config_settings(const std::shared_ptr& _config) _skip_domains.emplace("kernel_dispatch"); _skip_domains.emplace("page_migration"); - _skip_domains.emplace("scratch_memory"); _add_operation_settings( "MARKER_API", callback_tracing_info[ROCPROFILER_CALLBACK_TRACING_MARKER_CORE_API], @@ -652,7 +651,7 @@ get_backtrace_operations(rocprofiler_callback_tracing_kind_t kindv) { if(callback_operation_option_names.count(kindv) == 0) { - LOG_CRITICAL("callback_operation_operation_names does not have value for {}", + LOG_CRITICAL("callback_operation_option_names does not have value for {}", static_cast(kindv)); ::rocprofsys::set_state(::rocprofsys::State::Finalized); std::abort(); diff --git a/projects/rocprofiler-systems/source/lib/core/trace_cache/cache_manager.hpp b/projects/rocprofiler-systems/source/lib/core/trace_cache/cache_manager.hpp index 47e8cd2a5a..98c1a2880c 100644 --- a/projects/rocprofiler-systems/source/lib/core/trace_cache/cache_manager.hpp +++ b/projects/rocprofiler-systems/source/lib/core/trace_cache/cache_manager.hpp @@ -41,7 +41,7 @@ using storage_parser_t = storage_parser; + backtrace_region_sample, scratch_memory_sample>; using buffer_storage_t = buffer_storage; diff --git a/projects/rocprofiler-systems/source/lib/core/trace_cache/perfetto_processor.cpp b/projects/rocprofiler-systems/source/lib/core/trace_cache/perfetto_processor.cpp index 92a25255e5..6303824aa8 100644 --- a/projects/rocprofiler-systems/source/lib/core/trace_cache/perfetto_processor.cpp +++ b/projects/rocprofiler-systems/source/lib/core/trace_cache/perfetto_processor.cpp @@ -540,6 +540,72 @@ perfetto_processor_t::handle([[maybe_unused]] const kernel_dispatch_sample& _kds #endif } +void +perfetto_processor_t::handle([[maybe_unused]] const scratch_memory_sample& _sms) +{ +#if ROCPROFSYS_USE_ROCM > 0 + auto _corr_id = _sms.correlation_id_internal; + auto _stream_id = _sms.stream_handle; + auto _queue_id_handle = _sms.queue_id_handle; + const auto& _t_info = thread_info::get(_sms.thread_id, SystemTID); + const auto _thread_id_sequent = _t_info->index_data->sequent_value; + auto _beg_ts = _sms.start_timestamp; + auto _end_ts = _sms.end_timestamp; + + auto _agent_device_id = + m_agent_manager.get_agent_by_handle(_sms.agent_id_handle).device_type_index; + auto _name = std::string{ m_metadata.get_buffer_name_info().at( + static_cast(_sms.kind), + static_cast(_sms.operation)) }; + +// Scratch memory samples from SDK versions prior to 7.0.2 do not include +// allocation_size field, so counter tracks are not needed +# if ROCPROFSYS_ROCM_VERSION >= 70002 + using counter_track = + perfetto_counter_track; + + if(!counter_track::exists(_agent_device_id)) + { + auto _track_desc_alloc_size = JOIN("", "GPU Scratch Memory [", _agent_device_id, + "] Thread ", _thread_id_sequent); + counter_track::emplace(_agent_device_id, _track_desc_alloc_size, "bytes"); + } + + if(_sms.operation == ROCPROFILER_SCRATCH_MEMORY_ALLOC) + { + TRACE_COUNTER("rocm_scratch_memory", counter_track::at(_agent_device_id, 0), + _beg_ts, _sms.allocation_size); + } +# endif + + auto _track_desc_events = [&]() { + return JOIN("", "GPU Scratch Memory Events Thread ", _thread_id_sequent); + }; + + const auto _track = + tracing::get_perfetto_track(category::rocm_scratch_memory{}, _track_desc_events); + + auto add_perfetto_annotations = [&](::perfetto::EventContext ctx) { + if(!m_use_annotations) return; + + annotate_perfetto(ctx, { { "begin_ns", _beg_ts }, + { "end_ns", _end_ts }, + { "corr_id", _corr_id }, + { "stream_id", _stream_id }, + { "queue", _queue_id_handle }, + { "allocation_size", _sms.allocation_size }, + { "agent_id", _agent_device_id }, + { "operation", _name }, + { "flags", _sms.flags } }); + }; + + tracing::push_perfetto(category::rocm_scratch_memory{}, _name.c_str(), _track, + _beg_ts, ::perfetto::Flow::ProcessScoped(_corr_id), + add_perfetto_annotations); + tracing::pop_perfetto(category::rocm_scratch_memory{}, "", _track, _end_ts); +#endif +} + void perfetto_processor_t::handle([[maybe_unused]] const memory_copy_sample& _mcs) { diff --git a/projects/rocprofiler-systems/source/lib/core/trace_cache/perfetto_processor.hpp b/projects/rocprofiler-systems/source/lib/core/trace_cache/perfetto_processor.hpp index 5ddb2410b6..4dd487a657 100644 --- a/projects/rocprofiler-systems/source/lib/core/trace_cache/perfetto_processor.hpp +++ b/projects/rocprofiler-systems/source/lib/core/trace_cache/perfetto_processor.hpp @@ -56,6 +56,7 @@ public: void finalize_processing(); void handle(const kernel_dispatch_sample& sample); + void handle(const scratch_memory_sample& sample); void handle(const memory_copy_sample& sample); void handle(const memory_allocate_sample& sample); void handle(const region_sample& sample); diff --git a/projects/rocprofiler-systems/source/lib/core/trace_cache/rocpd_processor.cpp b/projects/rocprofiler-systems/source/lib/core/trace_cache/rocpd_processor.cpp index 567b1de230..cded11c3a8 100644 --- a/projects/rocprofiler-systems/source/lib/core/trace_cache/rocpd_processor.cpp +++ b/projects/rocprofiler-systems/source/lib/core/trace_cache/rocpd_processor.cpp @@ -66,6 +66,37 @@ get_handle_from_code_object( # endif } #endif + +#if ROCPROFSYS_USE_ROCM > 0 +using memory_operation = std::string; +using memory_type = std::string; +std::pair +parse_memory_operation_name(std::string_view memory_operation_name) +{ + static const std::unordered_map> + parsing_map{ + { "MEMORY_ALLOCATION_NONE", { "NONE", "REAL" } }, + { "MEMORY_ALLOCATION_ALLOCATE", { "ALLOC", "REAL" } }, + { "MEMORY_ALLOCATION_VMEM_ALLOCATE", { "ALLOC", "VIRTUAL" } }, + { "MEMORY_ALLOCATION_FREE", { "FREE", "REAL" } }, + { "MEMORY_ALLOCATION_VMEM_FREE", { "FREE", "VIRTUAL" } }, + { "SCRATCH_MEMORY_NONE", { "NONE", "SCRATCH" } }, + { "SCRATCH_MEMORY_ALLOC", { "ALLOC", "SCRATCH" } }, + { "SCRATCH_MEMORY_FREE", { "FREE", "SCRATCH" } }, + { "SCRATCH_MEMORY_ASYNC_RECLAIM", { "ASYNC_RECLAIM", "SCRATCH" } }, + }; + + auto item = parsing_map.find(memory_operation_name); + if(item == parsing_map.end()) + { + LOG_WARNING("Unknown memory operation name: {}", memory_operation_name); + return { "UNKNOWN", "UNKNOWN" }; + } + + return item->second; +} +#endif } // namespace void @@ -110,6 +141,46 @@ rocpd_processor_t::handle([[maybe_unused]] const kernel_dispatch_sample& _kds) #endif } +void +rocpd_processor_t::handle([[maybe_unused]] const scratch_memory_sample& _sms) +{ +#if ROCPROFSYS_USE_ROCM > 0 + auto& n_info = node_info::get_instance(); + auto process = m_metadata->get_process_info(); + + const auto* _name = m_metadata->get_buffer_name_info().at( + static_cast(_sms.kind), + static_cast(_sms.operation)); + + auto agent_primary_key = + m_agent_manager->get_agent_by_handle(_sms.agent_id_handle).base_id; + + auto thread_primary_key = + m_data_processor->map_thread_id_to_primary_key(_sms.thread_id); + + auto category_primary_key = m_data_processor->insert_string( + trait::name::value); + + auto stack_id = _sms.correlation_id_internal; + auto parent_stack_id = _sms.correlation_id_ancestor; + auto correlation_id = 0; + auto address_value = 0; + + auto event_primary_key = m_data_processor->insert_event( + category_primary_key, stack_id, parent_stack_id, correlation_id); + + auto [memory_operation, memory_type] = parse_memory_operation_name(_name); + + auto extdata_json_str = JOIN("", "{\"flags\": ", _sms.flags, "}"); + + m_data_processor->insert_memory_alloc( + n_info.id, process.pid, thread_primary_key, agent_primary_key, + memory_operation.c_str(), memory_type.c_str(), _sms.start_timestamp, + _sms.end_timestamp, address_value, _sms.allocation_size, _sms.queue_id_handle, + _sms.stream_handle, event_primary_key, extdata_json_str.c_str()); +#endif +} + void rocpd_processor_t::handle([[maybe_unused]] const memory_copy_sample& _mcs) { @@ -153,46 +224,6 @@ void rocpd_processor_t::handle([[maybe_unused]] const memory_allocate_sample& _mas) { #if ROCPROFSYS_USE_ROCM > 0 && (ROCPROFILER_VERSION >= 600) - static auto memtype_to_db = - [](std::string_view memory_type) -> std::pair { - constexpr auto MEMORY_PREFIX = std::string_view{ "MEMORY_ALLOCATION_" }; - constexpr auto SCRATCH_PREFIX = std::string_view{ "SCRATCH_MEMORY_" }; - constexpr auto VMEM_PREFIX = std::string_view{ "VMEM_" }; - constexpr auto ASYNC_PREFIX = std::string_view{ "ASYNC_" }; - - std::string _type; - std::string _level; - if(memory_type.find(MEMORY_PREFIX) == 0) - { - _type = memory_type.substr(MEMORY_PREFIX.length()); - if(_type.find(VMEM_PREFIX) == 0) - { - _type = _type.substr(VMEM_PREFIX.length()); - _level = "VIRTUAL"; - } - else - { - _level = "REAL"; - } - } - else if(memory_type.find(SCRATCH_PREFIX) == 0) - { - _type = memory_type.substr(SCRATCH_PREFIX.length()); - _level = "SCRATCH"; - if(memory_type.find(ASYNC_PREFIX) == 0) - { - _type = memory_type.substr(ASYNC_PREFIX.length()); // RECLAIM - } - } - - if(_type == "ALLOCATE") - { - _type = "ALLOC"; - } - - return std::make_pair(_type, _level); - }; - auto& n_info = node_info::get_instance(); auto process = m_metadata->get_process_info(); auto thread_primary_key = @@ -210,7 +241,7 @@ rocpd_processor_t::handle([[maybe_unused]] const memory_allocate_sample& _mas) static_cast(_mas.kind), static_cast(_mas.operation)); - auto [type, level] = memtype_to_db(_name); + auto [memory_operation, memory_type] = parse_memory_operation_name(_name); auto stack_id = _mas.correlation_id_internal; auto parent_stack_id = _mas.correlation_id_ancestor; @@ -224,9 +255,10 @@ rocpd_processor_t::handle([[maybe_unused]] const memory_allocate_sample& _mas) category_primary_key, stack_id, parent_stack_id, correlation_id); m_data_processor->insert_memory_alloc( - n_info.id, process.pid, thread_primary_key, agent_primary_key, type.c_str(), - level.c_str(), _mas.start_timestamp, _mas.end_timestamp, _mas.address_value, - _mas.allocation_size, queue_id, _mas.stream_handle, event_primary_key); + n_info.id, process.pid, thread_primary_key, agent_primary_key, + memory_operation.c_str(), memory_type.c_str(), _mas.start_timestamp, + _mas.end_timestamp, _mas.address_value, _mas.allocation_size, queue_id, + _mas.stream_handle, event_primary_key); } #endif } diff --git a/projects/rocprofiler-systems/source/lib/core/trace_cache/rocpd_processor.hpp b/projects/rocprofiler-systems/source/lib/core/trace_cache/rocpd_processor.hpp index 68f299a3e6..78c1d25670 100644 --- a/projects/rocprofiler-systems/source/lib/core/trace_cache/rocpd_processor.hpp +++ b/projects/rocprofiler-systems/source/lib/core/trace_cache/rocpd_processor.hpp @@ -45,6 +45,7 @@ public: void finalize_processing(); void handle(const kernel_dispatch_sample& sample); + void handle(const scratch_memory_sample& sample); void handle(const memory_copy_sample& sample); void handle(const memory_allocate_sample& sample); void handle(const region_sample& sample); diff --git a/projects/rocprofiler-systems/source/lib/core/trace_cache/sample_processor.hpp b/projects/rocprofiler-systems/source/lib/core/trace_cache/sample_processor.hpp index b55d80740b..b94232ef16 100644 --- a/projects/rocprofiler-systems/source/lib/core/trace_cache/sample_processor.hpp +++ b/projects/rocprofiler-systems/source/lib/core/trace_cache/sample_processor.hpp @@ -43,6 +43,11 @@ struct processor_t static_cast(this)->handle(sample); } + void handle(const scratch_memory_sample& sample) + { + static_cast(this)->handle(sample); + } + void handle(const memory_copy_sample& sample) { static_cast(this)->handle(sample); @@ -84,6 +89,7 @@ protected: struct processor_view_t { using kernel_dispatch_fn_t = void (*)(void*, const kernel_dispatch_sample&) noexcept; + using scratch_memory_fn_t = void (*)(void*, const scratch_memory_sample&) noexcept; using memory_copy_fn_t = void (*)(void*, const memory_copy_sample&) noexcept; #if(ROCPROFILER_VERSION >= 600) using memory_allocate_fn_t = void (*)(void*, const memory_allocate_sample&) noexcept; @@ -101,6 +107,7 @@ struct processor_view_t struct vtable_t { kernel_dispatch_fn_t handle_kernel_dispatch; + scratch_memory_fn_t handle_scratch_memory; memory_copy_fn_t handle_memory_copy; #if(ROCPROFILER_VERSION >= 600) memory_allocate_fn_t handle_memory_allocate; @@ -134,6 +141,11 @@ struct processor_view_t m_vtable->handle_kernel_dispatch(m_object, sample); } + ROCPROFSYS_INLINE void handle(const scratch_memory_sample& sample) const noexcept + { + m_vtable->handle_scratch_memory(m_object, sample); + } + ROCPROFSYS_INLINE void handle(const memory_copy_sample& sample) const noexcept { m_vtable->handle_memory_copy(m_object, sample); @@ -194,6 +206,9 @@ private: +[](void* obj, const kernel_dispatch_sample& sample) noexcept { static_cast(obj)->handle(sample); }, + +[](void* obj, const scratch_memory_sample& sample) noexcept { + static_cast(obj)->handle(sample); + }, +[](void* obj, const memory_copy_sample& sample) noexcept { static_cast(obj)->handle(sample); }, @@ -275,6 +290,9 @@ struct sample_processor_t case type_identifier_t::kernel_dispatch: handle_sample(static_cast(sample)); break; + case type_identifier_t::scratch_memory: + handle_sample(static_cast(sample)); + break; case type_identifier_t::memory_copy: handle_sample(static_cast(sample)); break; diff --git a/projects/rocprofiler-systems/source/lib/core/trace_cache/sample_type.hpp b/projects/rocprofiler-systems/source/lib/core/trace_cache/sample_type.hpp index 9bd20bfc8c..d1119a44e4 100644 --- a/projects/rocprofiler-systems/source/lib/core/trace_cache/sample_type.hpp +++ b/projects/rocprofiler-systems/source/lib/core/trace_cache/sample_type.hpp @@ -46,6 +46,7 @@ enum class type_identifier_t : uint32_t amd_smi_sample = 0x0006, cpu_freq_sample = 0x0007, backtrace_region_sample = 0x0008, + scratch_memory = 0x0009, fragmented_space = 0xFFFF }; @@ -148,6 +149,83 @@ get_size(const kernel_dispatch_sample& item) item.grid_size_z, static_cast(item.stream_handle)); } +struct scratch_memory_sample : cacheable_t +{ + static constexpr type_identifier_t type_identifier = + type_identifier_t::scratch_memory; + + scratch_memory_sample() = default; + scratch_memory_sample(uint64_t _start_timestamp, uint64_t _end_timestamp, + uint64_t _thread_id, uint64_t _agent_id_handle, + uint64_t _queue_id_handle, int32_t _kind, int32_t _operation, + int32_t _flags, uint64_t _allocation_size, + uint64_t _correlation_id_internal, + uint64_t _correlation_id_ancestor, size_t _stream_handle) + : start_timestamp(_start_timestamp) + , end_timestamp(_end_timestamp) + , thread_id(_thread_id) + , agent_id_handle(_agent_id_handle) + , queue_id_handle(_queue_id_handle) + , kind(_kind) + , operation(_operation) + , flags(_flags) + , allocation_size(_allocation_size) + , correlation_id_internal(_correlation_id_internal) + , correlation_id_ancestor(_correlation_id_ancestor) + , stream_handle(_stream_handle) + {} + + uint64_t start_timestamp; + uint64_t end_timestamp; + uint64_t thread_id; + uint64_t agent_id_handle; + uint64_t queue_id_handle; + int32_t kind; + int32_t operation; + int32_t flags; + uint64_t allocation_size; + uint64_t correlation_id_internal; + uint64_t correlation_id_ancestor; + size_t stream_handle; +}; + +template <> +inline void +serialize(uint8_t* buffer, const scratch_memory_sample& item) +{ + utility::store_value(buffer, item.start_timestamp, item.end_timestamp, item.thread_id, + item.agent_id_handle, item.queue_id_handle, item.kind, + item.operation, item.flags, item.allocation_size, + item.correlation_id_internal, item.correlation_id_ancestor, + static_cast(item.stream_handle)); +} + +template <> +inline scratch_memory_sample +deserialize(uint8_t*& buffer) +{ + scratch_memory_sample item; + uint64_t stream_handle; + utility::parse_value(buffer, item.start_timestamp, item.end_timestamp, item.thread_id, + item.agent_id_handle, item.queue_id_handle, item.kind, + item.operation, item.flags, item.allocation_size, + item.correlation_id_internal, item.correlation_id_ancestor, + stream_handle); + item.stream_handle = stream_handle; + return item; +} + +template <> +inline size_t +get_size(const scratch_memory_sample& item) +{ + return utility::get_size(item.start_timestamp, item.end_timestamp, item.thread_id, + item.agent_id_handle, item.queue_id_handle, item.kind, + item.operation, item.flags, item.allocation_size, + item.correlation_id_internal, item.correlation_id_ancestor, + static_cast(item.stream_handle)); +} + struct memory_copy_sample : cacheable_t { static constexpr type_identifier_t type_identifier = type_identifier_t::memory_copy; diff --git a/projects/rocprofiler-systems/source/lib/rocprof-sys/library/rocprofiler-sdk.cpp b/projects/rocprofiler-systems/source/lib/rocprof-sys/library/rocprofiler-sdk.cpp index d30368650b..0a337b2400 100644 --- a/projects/rocprofiler-systems/source/lib/rocprof-sys/library/rocprofiler-sdk.cpp +++ b/projects/rocprofiler-systems/source/lib/rocprof-sys/library/rocprofiler-sdk.cpp @@ -567,6 +567,18 @@ get_mem_alloc_address( } #endif +uint64_t +get_scratch_mem_alloc_size( + [[maybe_unused]] const rocprofiler_buffer_tracing_scratch_memory_record_t& record) +{ +// Scratch memory samples from SDK versions prior to 7.0.2 do not include allocation_size +#if(ROCPROFSYS_USE_ROCM > 0 && ROCPROFSYS_ROCM_VERSION >= 70002) + return record.allocation_size; +#else + return 0; +#endif +} + void cache_region(const rocprofiler_callback_tracing_record_t* record, const rocprofiler_timestamp_t start_timestamp, @@ -615,13 +627,26 @@ cache_kernel_dispatch(rocprofiler_buffer_tracing_kernel_dispatch_record_t* recor record->dispatch_info.grid_size.z, stream_handle }); } +void +cache_scratch_memory(rocprofiler_buffer_tracing_scratch_memory_record_t* record, + uint64_t stream_handle) +{ + trace_cache::get_metadata_registry().add_stream(stream_handle); + trace_cache::get_buffer_storage().store(trace_cache::scratch_memory_sample{ + record->start_timestamp, record->end_timestamp, record->thread_id, + record->agent_id.handle, record->queue_id.handle, + static_cast(record->kind), static_cast(record->operation), + static_cast(record->flags), get_scratch_mem_alloc_size(*record), + record->correlation_id.internal, get_parent_stack_id(record->correlation_id), + stream_handle }); +} + void cache_memory_copy(rocprofiler_buffer_tracing_memory_copy_record_t* record, uint64_t stream_handle) { trace_cache::get_metadata_registry().add_stream(stream_handle); trace_cache::get_buffer_storage().store(trace_cache::memory_copy_sample{ - record->start_timestamp, record->end_timestamp, record->thread_id, record->dst_agent_id.handle, record->src_agent_id.handle, static_cast(record->kind), static_cast(record->operation), @@ -1759,6 +1784,120 @@ tool_tracing_buffered(rocprofiler_context_id_t /*context*/, } } } + else if(header->kind == ROCPROFILER_BUFFER_TRACING_SCRATCH_MEMORY) + { + auto* record = + static_cast( + header->payload); + + bool _group_by_queue = _default_group_by_queue; + + const auto* agent = tool_data->get_gpu_tool_agent(record->agent_id); + auto device_id = static_cast(agent->device_id); + + const auto& t_info = thread_info::get(record->thread_id, SystemTID); + auto thread_id_sequent = t_info->index_data->sequent_value; + + auto _corr_id = record->correlation_id.internal; + auto _beg_ns = record->start_timestamp; + auto _end_ns = record->end_timestamp; + auto _name = + tool_data->buffered_tracing_info.at(record->kind, record->operation); + + auto _stream_id = get_stream_id(record).handle; + if(_stream_id == 0) + { + // Scratch memory event is not associated with a HIP stream + _group_by_queue = true; + } + + { + auto track_name = JOIN("", "GPU Scratch Memory [", device_id, + "] Thread ", record->thread_id); + cache_category(); + cache_add_thread_info(record->thread_id); + cache_add_track(track_name.c_str(), record->thread_id); + cache_scratch_memory(record, _stream_id); + } + + if(get_use_timemory()) + { + auto _bundle = kernel_dispatch_bundle_t{ _name }; + + _bundle.push(thread_id_sequent).start().stop(); + _bundle.get([_beg_ns, _end_ns](tim::component::wall_clock* _wc) { + _wc->set_value(_end_ns - _beg_ns); + _wc->set_accum(_end_ns - _beg_ns); + }); + _bundle.pop(); + } + + if(get_use_perfetto()) + { +// Scratch memory samples from SDK versions prior to 7.0.2 do not include +// allocation_size field, so counter tracks are not needed +#if(ROCPROFSYS_USE_ROCM > 0 && ROCPROFSYS_ROCM_VERSION >= 70002) + using counter_track = perfetto_counter_track< + rocprofiler_buffer_tracing_scratch_memory_record_t>; + + if(!counter_track::exists(device_id)) + { + auto track_name_alloc_size = + JOIN("", "GPU Scratch Memory [", device_id, "] (S) Thread ", + thread_id_sequent); + counter_track::emplace(device_id, track_name_alloc_size, "bytes"); + } + + if(record->operation == ROCPROFILER_SCRATCH_MEMORY_ALLOC) + { + TRACE_COUNTER("rocm_scratch_memory", + counter_track::at(device_id, 0), _beg_ns, + record->allocation_size); + } +#endif + auto add_perfetto_annotations = [&](::perfetto::EventContext ctx) { + if(config::get_perfetto_annotations()) + { + tracing::add_perfetto_annotation(ctx, "begin_ns", _beg_ns); + tracing::add_perfetto_annotation(ctx, "end_ns", _end_ns); + tracing::add_perfetto_annotation(ctx, "corr_id", _corr_id); + tracing::add_perfetto_annotation(ctx, "stream_id", + _stream_id); + } + }; + + if(_group_by_queue) + { + auto track_name_events = [&]() { + return JOIN("", "GPU Scratch Memory (S) Events Thread ", + thread_id_sequent); + }; + const auto _track = tracing::get_perfetto_track( + category::rocm_scratch_memory{}, track_name_events); + + tracing::push_perfetto(category::rocm_scratch_memory{}, + _name.data(), _track, _beg_ns, + ::perfetto::Flow::ProcessScoped(_corr_id), + add_perfetto_annotations); + + tracing::pop_perfetto(category::rocm_scratch_memory{}, "", _track, + _end_ns); + } + else + { + const auto _track = tracing::get_perfetto_track( + category::rocm_hip_stream{}, _track_desc_stream, _stream_id); + + tracing::push_perfetto(category::rocm_hip_stream{}, _name.data(), + _track, _beg_ns, + ::perfetto::Flow::ProcessScoped(_corr_id), + add_perfetto_annotations); + + tracing::pop_perfetto(category::rocm_hip_stream{}, "", _track, + _end_ns); + } + } + } else if(header->kind == ROCPROFILER_BUFFER_TRACING_MEMORY_COPY) { auto* record = @@ -2249,6 +2388,17 @@ tool_init(rocprofiler_client_finalize_t fini_func, void* user_data) _data->primary_ctx, ROCPROFILER_BUFFER_TRACING_MEMORY_COPY, nullptr, 0, _data->memory_copy_buffer)); } + if(_buffered_domain.count(ROCPROFILER_BUFFER_TRACING_SCRATCH_MEMORY) > 0) + { + ROCPROFILER_CALL(rocprofiler_create_buffer( + _data->primary_ctx, buffer_size, watermark, + ROCPROFILER_BUFFER_POLICY_LOSSLESS, tool_tracing_buffered, tool_data, + &_data->scratch_memory_buffer)); + + ROCPROFILER_CALL(rocprofiler_configure_buffer_tracing_service( + _data->primary_ctx, ROCPROFILER_BUFFER_TRACING_SCRATCH_MEMORY, nullptr, 0, + _data->scratch_memory_buffer)); + } #if(ROCPROFILER_VERSION >= 600) if(_buffered_domain.count(ROCPROFILER_BUFFER_TRACING_MEMORY_ALLOCATION) > 0) diff --git a/projects/rocprofiler-systems/source/lib/rocprof-sys/library/rocprofiler-sdk/fwd.hpp b/projects/rocprofiler-systems/source/lib/rocprof-sys/library/rocprofiler-sdk/fwd.hpp index fa75982db4..48d4714044 100644 --- a/projects/rocprofiler-systems/source/lib/rocprof-sys/library/rocprofiler-sdk/fwd.hpp +++ b/projects/rocprofiler-systems/source/lib/rocprof-sys/library/rocprofiler-sdk/fwd.hpp @@ -122,7 +122,7 @@ using backtrace_operation_map_t = struct client_data { - static constexpr size_t num_buffers = 4; + static constexpr size_t num_buffers = 5; static constexpr size_t num_contexts = 2; using buffer_name_info_t = rocprofiler::sdk::buffer_name_info_t; @@ -138,6 +138,7 @@ struct client_data rocprofiler_context_id_t primary_ctx = { 0 }; rocprofiler_context_id_t counter_ctx = { 0 }; rocprofiler_buffer_id_t kernel_dispatch_buffer = { 0 }; + rocprofiler_buffer_id_t scratch_memory_buffer = { 0 }; rocprofiler_buffer_id_t memory_copy_buffer = { 0 }; rocprofiler_buffer_id_t memory_alloc_buffer = { 0 }; rocprofiler_buffer_id_t counter_collection_buffer = { 0 }; @@ -179,12 +180,9 @@ client_data::get_contexts() const inline client_data::buffer_id_vec_t client_data::get_buffers() const { - return buffer_id_vec_t{ - kernel_dispatch_buffer, - memory_copy_buffer, - memory_alloc_buffer, - counter_collection_buffer, - }; + return buffer_id_vec_t{ kernel_dispatch_buffer, scratch_memory_buffer, + memory_copy_buffer, memory_alloc_buffer, + counter_collection_buffer }; } inline const rocprofsys_agent_t* From 88f07baa927787677fc414264935526761846cad Mon Sep 17 00:00:00 2001 From: "systems-assistant[bot]" <221163467+systems-assistant[bot]@users.noreply.github.com> Date: Mon, 19 Jan 2026 09:17:00 -0800 Subject: [PATCH 10/21] SWDEV-493792 - add split barriers for grid_group (#508) * SWDEV-493792 - add split barriers for grid_group * add tests * Update change log * Add Navi4 split barrier * Update docs * Use new Catch2 Approx macro * Update split_barrier.cc to check for coop groups --------- Co-authored-by: Jatin Chaudhary Co-authored-by: Jatin Chaudhary <51944368+cjatin@users.noreply.github.com> --- projects/clr/CHANGELOG.md | 1 + .../amd_detail/amd_hip_cooperative_groups.h | 21 +++ .../hip/amd_detail/device_library_decls.h | 2 + .../hip_cooperative_groups_helper.h | 20 +++ .../catch/unit/cooperativeGrps/CMakeLists.txt | 1 + .../unit/cooperativeGrps/split_barrier.cc | 123 ++++++++++++++++++ .../hip_runtime_api/cooperative_groups.rst | 1 - 7 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 projects/hip-tests/catch/unit/cooperativeGrps/split_barrier.cc diff --git a/projects/clr/CHANGELOG.md b/projects/clr/CHANGELOG.md index 292125904d..80756af55e 100644 --- a/projects/clr/CHANGELOG.md +++ b/projects/clr/CHANGELOG.md @@ -8,6 +8,7 @@ Full documentation for HIP is available at [rocm.docs.amd.com](https://rocm.docs * New HIP APIs - `hipKernelGetParamInfo` returns the offset and size of a kernel parameter +* Support for `barrier_arrive` and `barrier_wait` for `grid_group` and `thread_block`. * New HIP supports - `grid_group::block_rank()` returns the rank of the block in the calling thread diff --git a/projects/clr/hipamd/include/hip/amd_detail/amd_hip_cooperative_groups.h b/projects/clr/hipamd/include/hip/amd_detail/amd_hip_cooperative_groups.h index 62cb66fb90..80b7f71c23 100644 --- a/projects/clr/hipamd/include/hip/amd_detail/amd_hip_cooperative_groups.h +++ b/projects/clr/hipamd/include/hip/amd_detail/amd_hip_cooperative_groups.h @@ -212,6 +212,19 @@ class grid_group : public thread_group { //! @copydoc thread_group::sync __CG_QUALIFIER__ void sync() const { internal::grid::sync(); } __CG_QUALIFIER__ dim3 group_dim() const { return internal::grid::grid_dim(); } + struct arrival_token { + unsigned int signal; + }; + //! Arrive at a barrier + __CG_QUALIFIER__ arrival_token barrier_arrive() const { + arrival_token t; + t.signal = internal::grid::barrier_signal(); + return t; + } + //! Arrive at a barrier + __CG_QUALIFIER__ void barrier_wait(arrival_token&& t) const { + internal::grid::barrier_wait(t.signal); + } }; /** \ingroup CooperativeGConstruct @@ -295,6 +308,14 @@ class thread_block : public thread_group { __CG_STATIC_QUALIFIER__ void sync() { internal::workgroup::sync(); } //! Returns the group dimensions. __CG_QUALIFIER__ dim3 group_dim() { return internal::workgroup::block_dim(); } + struct arrival_token {}; + //! Arrive at a barrier + __CG_QUALIFIER__ arrival_token barrier_arrive() const { + internal::workgroup::barrier_arrive(); + return arrival_token{}; + } + //! Arrive at a barrier + __CG_QUALIFIER__ void barrier_wait(arrival_token&&) const { internal::workgroup::barrier_wait(); } }; /** \ingroup CooperativeGConstruct diff --git a/projects/clr/hipamd/include/hip/amd_detail/device_library_decls.h b/projects/clr/hipamd/include/hip/amd_detail/device_library_decls.h index 39c2e59686..791d2e7137 100644 --- a/projects/clr/hipamd/include/hip/amd_detail/device_library_decls.h +++ b/projects/clr/hipamd/include/hip/amd_detail/device_library_decls.h @@ -97,6 +97,8 @@ extern "C" __device__ __attribute__((const)) uint __ockl_multi_grid_size(void); extern "C" __device__ __attribute__((const)) uint __ockl_multi_grid_thread_rank(void); extern "C" __device__ __attribute__((const)) int __ockl_multi_grid_is_valid(void); extern "C" __device__ __attribute__((convergent)) void __ockl_multi_grid_sync(void); +extern "C" __device__ __attribute__((const)) uint __ockl_grid_bar_arrive(void); +extern "C" __device__ __attribute__((convergent)) void __ockl_grid_bar_wait(uint); extern "C" __device__ void __ockl_atomic_add_noret_f32(float*, float); diff --git a/projects/clr/hipamd/include/hip/amd_detail/hip_cooperative_groups_helper.h b/projects/clr/hipamd/include/hip/amd_detail/hip_cooperative_groups_helper.h index d9671eb342..771e8419ff 100644 --- a/projects/clr/hipamd/include/hip/amd_detail/hip_cooperative_groups_helper.h +++ b/projects/clr/hipamd/include/hip/amd_detail/hip_cooperative_groups_helper.h @@ -196,6 +196,9 @@ __CG_STATIC_QUALIFIER__ dim3 grid_dim() { static_cast<__hip_uint32_t>(gridDim.z))); } +__CG_STATIC_QUALIFIER__ unsigned int barrier_signal() { return __ockl_grid_bar_arrive(); } + +__CG_STATIC_QUALIFIER__ void barrier_wait(unsigned int s) { __ockl_grid_bar_wait(s); } } // namespace grid /** @@ -238,6 +241,23 @@ __CG_STATIC_QUALIFIER__ dim3 block_dim() { static_cast<__hip_uint32_t>(blockDim.z))); } +__CG_STATIC_QUALIFIER__ void barrier_arrive() { + __builtin_amdgcn_fence(__ATOMIC_RELEASE, "workgroup"); +#if __has_builtin(__builtin_amdgcn_s_barrier_signal) && \ + __has_builtin(__builtin_amdgcn_s_barrier_wait) + __builtin_amdgcn_s_barrier_signal(-1); +#endif // __builtin_amdgcn_s_barrier_signal && __builtin_amdgcn_s_barrier_wait +} + +__CG_STATIC_QUALIFIER__ void barrier_wait() { +#if __has_builtin(__builtin_amdgcn_s_barrier_signal) && \ + __has_builtin(__builtin_amdgcn_s_barrier_wait) + __builtin_amdgcn_s_barrier_wait(-1); +#else + __builtin_amdgcn_s_barrier(); +#endif // __builtin_amdgcn_s_barrier_signal && __builtin_amdgcn_s_barrier_wait + __builtin_amdgcn_fence(__ATOMIC_ACQUIRE, "workgroup"); +} } // namespace workgroup namespace tiled_group { diff --git a/projects/hip-tests/catch/unit/cooperativeGrps/CMakeLists.txt b/projects/hip-tests/catch/unit/cooperativeGrps/CMakeLists.txt index f22d40f944..c0d2a00e3c 100644 --- a/projects/hip-tests/catch/unit/cooperativeGrps/CMakeLists.txt +++ b/projects/hip-tests/catch/unit/cooperativeGrps/CMakeLists.txt @@ -20,6 +20,7 @@ set(TEST_SRC binary_partition.cc cg_ballot.cc cg_any_all.cc + split_barrier.cc ) if(HIP_PLATFORM STREQUAL "nvidia") diff --git a/projects/hip-tests/catch/unit/cooperativeGrps/split_barrier.cc b/projects/hip-tests/catch/unit/cooperativeGrps/split_barrier.cc new file mode 100644 index 0000000000..f7376b6605 --- /dev/null +++ b/projects/hip-tests/catch/unit/cooperativeGrps/split_barrier.cc @@ -0,0 +1,123 @@ +/* +Copyright (c) 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. +*/ + +#include +#include + +static __global__ void wg_split_barrier(float *out, float *in) { + namespace cg = cooperative_groups; + + __shared__ float mid[32]; + size_t i = threadIdx.x; + auto tb = cg::this_thread_block(); + + out[i] = in[i] * 2.0f; + + auto tok = tb.barrier_arrive(); + + // use tid 0 to populate shared mem + if (i == 0) { + for (size_t j = 0; j < 32; j++) { + mid[j] = in[j]; + } + } + + tb.barrier_wait(std::move(tok)); + + out[i] += mid[i]; +} + +TEST_CASE("Unit_coop_thread_block_split_barrier") { + constexpr size_t size = 32; + float *d_out, *d_in; + + HIP_CHECK(hipMalloc(&d_out, sizeof(float) * size)); + HIP_CHECK(hipMalloc(&d_in, sizeof(float) * size)); + + std::vector in(size, 0.0f), out = in; + for (size_t i = 0; i < size; i++) { + in[i] = i + 1; + } + + HIP_CHECK(hipMemset(d_out, 0, sizeof(float) * size)); + HIP_CHECK( + hipMemcpy(d_in, in.data(), sizeof(float) * size, hipMemcpyHostToDevice)); + wg_split_barrier<<<1, size>>>(d_out, d_in); + HIP_CHECK(hipMemcpy(out.data(), d_out, sizeof(float) * size, + hipMemcpyDeviceToHost)); + + HIP_CHECK(hipFree(d_out)); + HIP_CHECK(hipFree(d_in)); + + for (size_t i = 0; i < size; i++) { + INFO("Index: " << i << " in: " << in[i] << " out: " << out[i]); + REQUIRE((in[i] * 3.0f) == Catch::Approx(out[i])); + } +} + +static __global__ void grid_split_barrier(int *data, int *result, int N) { + namespace cg = cooperative_groups; + cg::grid_group grid = cg::this_grid(); + + int gid = blockIdx.x * blockDim.x + threadIdx.x; + auto tok = grid.barrier_arrive(); + if (gid < N) { + data[gid] = gid + 1; + } + + grid.barrier_wait(std::move(tok)); + + if (grid.thread_rank() == 0) { + int sum = 0; + for (int i = 0; i < N; i++) + sum += data[i]; + *result = sum; + } +} + +TEST_CASE("Unit_coop_grids_split_barrier") { + hipDeviceProp_t prop; + HIP_CHECK(hipGetDeviceProperties(&prop, 0)); + + if (prop.cooperativeLaunch != 0) { + int N = 1024; + const int threads = 128; + const int blocks = (N + threads - 1) / threads; + + int *d_in, *d_out; + HIP_CHECK(hipMalloc(&d_in, N * sizeof(int))); + HIP_CHECK(hipMalloc(&d_out, sizeof(int))); + + void *args[] = {&d_in, &d_out, &N}; + + dim3 grid(blocks); + dim3 block(threads); + + HIP_CHECK(hipLaunchCooperativeKernel((void *)grid_split_barrier, grid, + block, args, 0, 0)); + HIP_CHECK(hipDeviceSynchronize()); + + int out = 0; + HIP_CHECK(hipMemcpy(&out, d_out, sizeof(int), hipMemcpyDeviceToHost)); + + HIP_CHECK(hipFree(d_in)); + HIP_CHECK(hipFree(d_out)); + REQUIRE(out == ((N * (N + 1)) / 2)); + } +} diff --git a/projects/hip/docs/how-to/hip_runtime_api/cooperative_groups.rst b/projects/hip/docs/how-to/hip_runtime_api/cooperative_groups.rst index a3e32cd294..bf34ab7583 100644 --- a/projects/hip/docs/how-to/hip_runtime_api/cooperative_groups.rst +++ b/projects/hip/docs/how-to/hip_runtime_api/cooperative_groups.rst @@ -494,7 +494,6 @@ HIP doesn't support the following CUDA functions/operators in ``cooperative_grou * ``synchronize`` * ``memcpy_async`` * ``wait`` and ``wait_prior`` -* ``barrier_arrive`` and ``barrier_wait`` * ``invoke_one`` and ``invoke_one_broadcast`` * ``reduce`` * ``reduce_update_async`` and ``reduce_store_async`` From 0254181f427a83da48ec190570242bb5b0a6d61d Mon Sep 17 00:00:00 2001 From: vedithal-amd Date: Mon, 19 Jan 2026 15:25:43 -0500 Subject: [PATCH 11/21] [rocprofiler-compute] Analysis Database Schema Improvements (v1.2.0) (#2526) * Analysis database v1.2.0 * `pc_sampling` and `roofline_data` tables should relate to `kernel` table instead of `workload` table * Remove `kernel_name` fields in `pc_sampling` and `roofline_data` table * Add kernel existence check for roofline data to prevent KeyError (#2536) * Initial plan * Add kernel existence check for roofline data to prevent KeyError Co-authored-by: vedithal-amd <191402304+vedithal-amd@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: vedithal-amd <191402304+vedithal-amd@users.noreply.github.com> * Optimize analysis performance * Refactor database schema: separate metric definitions from kernels Reorganize the database ORM to decouple metric definitions from kernel objects. This improves the schema design by: - Rename Metric -> MetricDefinition and Value -> MetricValue for clarity - Move metric definitions from kernel-level to workload-level, since metric definitions are shared across kernels - Update relationships: MetricDefinition belongs to Workload, MetricValue references both MetricDefinition and Kernel - Refactor metric_view to join through the new schema structure - Update test fixtures to use renamed table and class names - Update documentation with new example output using nbody workload - Regenerate database schema and views diagrams * Add min amd max aggregation in kernel_view * Add primary key id from tables into the view --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: vedithal-amd <191402304+vedithal-amd@users.noreply.github.com> --- .../.pre-commit-config.yaml | 4 +- .../analyze/analysis_data_dump_schema.png | Bin 189737 -> 259709 bytes .../data/analyze/analysis_data_dump_views.png | Bin 34622 -> 246107 bytes .../docs/how-to/analyze/cli.rst | 68 ++++---- .../rocprof_compute_analyze/analysis_db.py | 156 +++++++++++------- .../src/utils/analysis_orm.py | 105 +++++++----- .../tests/test_profile_general.py | 8 +- 7 files changed, 201 insertions(+), 140 deletions(-) diff --git a/projects/rocprofiler-compute/.pre-commit-config.yaml b/projects/rocprofiler-compute/.pre-commit-config.yaml index 2b36616c96..29831ddc66 100644 --- a/projects/rocprofiler-compute/.pre-commit-config.yaml +++ b/projects/rocprofiler-compute/.pre-commit-config.yaml @@ -2,7 +2,7 @@ default_stages: [pre-commit] fail_fast: true repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: check-yaml - id: end-of-file-fixer @@ -12,7 +12,7 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. Check https://github.com/astral-sh/ruff-pre-commit#version-compatibility # for the latest ruff version supported by the hook. - rev: v0.12.12 + rev: v0.14.11 hooks: - id: ruff-check args: [--fix] diff --git a/projects/rocprofiler-compute/docs/data/analyze/analysis_data_dump_schema.png b/projects/rocprofiler-compute/docs/data/analyze/analysis_data_dump_schema.png index 274b6f0020c2aa20f44950a4a0fe82bb8d6bed6a..24004d38257d39284c5d74f981c083316baa8871 100644 GIT binary patch literal 259709 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�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 ghK2zJ@#|_ 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

@43V0F@gi_-=JYm2&y{e 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

UEvB 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%0AsmiP)N(Pvg>!9lcd72xZ4Eah4i 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 z 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 diff --git a/projects/rocprofiler-compute/docs/how-to/analyze/cli.rst b/projects/rocprofiler-compute/docs/how-to/analyze/cli.rst index 984d226aaa..26238c154c 100644 --- a/projects/rocprofiler-compute/docs/how-to/analyze/cli.rst +++ b/projects/rocprofiler-compute/docs/how-to/analyze/cli.rst @@ -15,7 +15,7 @@ This section provides an overview of ROCm Compute Profiler's CLI analysis featur * :ref:`Metric customization `: Isolate a subset of built-in metrics or build your own profiling configuration. * :ref:`Filtering `: Hone in on a particular kernel, GPU ID, or dispatch ID via post-process filtering. - + * :ref:`Per-kernel roofline analysis `: Detailed arithmetic intensity and performance analysis for individual kernels. Run ``rocprof-compute analyze -h`` for more details. @@ -534,36 +534,46 @@ Analysis database example .. code-block:: shell-session - $ rocprof-compute analyze --verbose --db test -p workloads/vmem/MI300X_A1 -p workloads/vmem1/MI300X_A1 + $ rocprof-compute analyze --verbose --output-name test --output-format db -p workloads/nbody/MI300X_A1 -p workloads/nbody1/MI300X_A1 DEBUG Execution mode = analyze - __ _ - _ __ ___ ___ _ __ _ __ ___ / _| ___ ___ _ __ ___ _ __ _ _| |_ ___ - | '__/ _ \ / __| '_ \| '__/ _ \| |_ _____ / __/ _ \| '_ ` _ \| '_ \| | | | __/ _ \ - | | | (_) | (__| |_) | | | (_) | _|_____| (_| (_) | | | | | | |_) | |_| | || __/ - |_| \___/ \___| .__/|_| \___/|_| \___\___/|_| |_| |_| .__/ \__,_|\__\___| - |_| |_| + __ _ + _ __ ___ ___ _ __ _ __ ___ / _| ___ ___ _ __ ___ _ __ _ _| |_ ___ +| '__/ _ \ / __| '_ \| '__/ _ \| |_ _____ / __/ _ \| '_ ` _ \| '_ \| | | | __/ _ \ +| | | (_) | (__| |_) | | | (_) | _|_____| (_| (_) | | | | | | |_) | |_| | || __/ +|_| \___/ \___| .__/|_| \___/|_| \___\___/|_| |_| |_| .__/ \__,_|\__\___| + |_| |_| - INFO Analysis mode = db - DEBUG [omnisoc init] - DEBUG [omnisoc init] - DEBUG [analysis] prepping to do some analysis - INFO [analysis] deriving rocprofiler-compute metrics... - WARNING Roofline ceilings not found for /app/projects/rocprofiler-compute/workloads/vmem/MI300X_A1. - WARNING Roofline ceilings not found for /app/projects/rocprofiler-compute/workloads/vmem1/MI300X_A1. - WARNING PC sampling data not found for /app/projects/rocprofiler-compute/workloads/vmem/MI300X_A1. - WARNING PC sampling data not found for /app/projects/rocprofiler-compute/workloads/vmem1/MI300X_A1. - DEBUG Collected dispatch data - DEBUG Applied analysis mode filters - DEBUG Calculated dispatch data - DEBUG Collected metrics data - WARNING Failed to evaluate expression for 3.1.39 - Value: to_round((to_avg( + INFO Analysis mode = db + INFO ed45b0b189 + DEBUG [omnisoc init] + INFO ed45b0b189 + DEBUG [omnisoc init] + DEBUG [analysis] prepping to do some analysis + INFO [analysis] deriving rocprofiler-compute metrics... + DEBUG Collected roofline ceilings +WARNING PC sampling data not found for /app/projects/rocprofiler-compute/workloads/nbody/MI300X_A1. +WARNING PC sampling data not found for /app/projects/rocprofiler-compute/workloads/nbody1/MI300X_A1. + DEBUG Collected dispatch data + DEBUG Applied analysis mode filters + DEBUG Calculated dispatch data + DEBUG Collected metrics data +WARNING Failed to evaluate expression for 3.1.39 - Value: to_round((to_avg( (pmc_df.get("pmc_perf_ACCUM") / pmc_df.get("SQC_ICACHE_REQ")).where((pmc_df.get("SQC_ICACHE_REQ") != 0), None)) * 100), 0) - unsupported operand type(s) for /: 'NoneType' and 'float' - WARNING Failed to evaluate expression for 3.1.39 - Value: to_round((to_avg( +WARNING Failed to evaluate expression for 3.1.39 - Value: to_round((to_avg( (pmc_df.get("pmc_perf_ACCUM") / pmc_df.get("SQC_ICACHE_REQ")).where((pmc_df.get("SQC_ICACHE_REQ") != 0), None)) * 100), 0) - unsupported operand type(s) for /: 'NoneType' and 'float' - DEBUG Calculated metric values - DEBUG Calculated roofline data points - DEBUG [analysis] generating analysis - DEBUG SQLite database initialized with name: test.db - DEBUG Initialized database: test.db - DEBUG Completed writing database \ No newline at end of file + DEBUG Calculating expressions for kernel: _ZN12rocrand_impl6system6detail17trampoline_kernelINS_4host33static_block_size_config_providerILj256EEEjLb0ELNS3_11target_archE942EZNS3_25xorwow_generator_templateINS0_13device_systemENS3_23default_config_providerIL16rocrand_rng_type401EEEE4initEvEUlT_DpT0_E_JPN14rocrand_device13xorwow_engineEjjyyEEEvT3_DpT4_ + DEBUG Calculating expressions for kernel: _ZN12rocrand_impl6system6detail17trampoline_kernelINS_4host23default_config_providerIL16rocrand_rng_type401EEEfLb0ELNS3_11target_archE942EZZNS3_25xorwow_generator_templateINS0_13device_systemES6_E8generateIfNS3_20uniform_distributionIfjEEEE14rocrand_statusPT_mT0_ENKUlSF_E_clISt17integral_constantIbLb0EEEEDaSF_EUlSF_DpT0_E_JPN14rocrand_device13xorwow_engineEjPfmSD_EEEvT3_DpT4_ + DEBUG Calculating expressions for kernel: void bodyForce_block<256>(HIP_vector_type const*, HIP_vector_type*, float, int) + DEBUG Calculating expressions for kernel: _ZN12rocrand_impl6system6detail17trampoline_kernelINS_4host33static_block_size_config_providerILj256EEEjLb0ELNS3_11target_archE942EZNS3_25xorwow_generator_templateINS0_13device_systemENS3_23default_config_providerIL16rocrand_rng_type401EEEE4initEvEUlT_DpT0_E_JPN14rocrand_device13xorwow_engineEjjyyEEEvT3_DpT4_ + DEBUG Calculating expressions for kernel: _ZN12rocrand_impl6system6detail17trampoline_kernelINS_4host23default_config_providerIL16rocrand_rng_type401EEEfLb0ELNS3_11target_archE942EZZNS3_25xorwow_generator_templateINS0_13device_systemES6_E8generateIfNS3_20uniform_distributionIfjEEEE14rocrand_statusPT_mT0_ENKUlSF_E_clISt17integral_constantIbLb0EEEEDaSF_EUlSF_DpT0_E_JPN14rocrand_device13xorwow_engineEjPfmSD_EEEvT3_DpT4_ + DEBUG Calculating expressions for kernel: void bodyForce_block<256>(HIP_vector_type const*, HIP_vector_type*, float, int) + DEBUG Calculated metric values + DEBUG Calculated roofline data points + DEBUG [analysis] generating analysis + DEBUG SQLite database initialized with name: test.db + DEBUG Initialized database: test.db + INFO ed45b0b189 + INFO ed45b0b189 + DEBUG Completed writing database +WARNING Created file: test.db diff --git a/projects/rocprofiler-compute/src/rocprof_compute_analyze/analysis_db.py b/projects/rocprofiler-compute/src/rocprof_compute_analyze/analysis_db.py index 4a121499f7..1a01b23a55 100644 --- a/projects/rocprofiler-compute/src/rocprof_compute_analyze/analysis_db.py +++ b/projects/rocprofiler-compute/src/rocprof_compute_analyze/analysis_db.py @@ -101,7 +101,9 @@ class db_analysis(OmniAnalyze_Base): Database.init(db_name) console_debug(f"Initialized database: {db_name}") + # Iterate over all workloads for workload_path in self._runs.keys(): + # Add workload workload_obj = orm.Workload( name=workload_path.split("/")[-2], sub_name=workload_path.split("/")[-1], @@ -113,38 +115,9 @@ class db_analysis(OmniAnalyze_Base): ) Database.get_session().add(workload_obj) - for pc_sample in self._pc_sampling_data_per_workload.get( - workload_path, pd.DataFrame() - ).itertuples(): - Database.get_session().add( - orm.PCsampling( - source=pc_sample.source_line, - instruction=pc_sample.instruction, - count=pc_sample.count, - kernel_name=pc_sample.kernel_name, - offset=pc_sample.offset, - count_issue=pc_sample.count_issued, - count_stall=pc_sample.count_stalled, - stall_reason=pc_sample.stall_reason, - workload=workload_obj, - ) - ) - - for roofline_data in self._roofline_data_per_workload.get( - workload_path, pd.DataFrame() - ).itertuples(): - Database.get_session().add( - orm.RooflineData( - kernel_name=roofline_data.kernel_name, - total_flops=roofline_data.total_flops, - l1_cache_data=roofline_data.l1_cache_data, - l2_cache_data=roofline_data.l2_cache_data, - hbm_cache_data=roofline_data.hbm_cache_data, - workload=workload_obj, - ) - ) - + # Add kernel kernel_objs: dict[str, orm.Kernel] = {} + for dispatch in self._dispatch_data_per_workload.get( workload_path, pd.DataFrame() ).itertuples(): @@ -167,44 +140,101 @@ class db_analysis(OmniAnalyze_Base): ) ) - # Optimize: Pre-group values by (metric_id, kernel_name) for O(1) lookups - values_df = self._values_data_per_workload.get( - workload_path, pd.DataFrame() - ) - values_grouped = {} - if not values_df.empty: - for value in values_df.itertuples(): - key = (value.metric_id, value.kernel_name) - if key not in values_grouped: - values_grouped[key] = [] - values_grouped[key].append(value) - - for metric in self._metrics_info_data_per_workload.get( + # Add roofline data points + for roofline_data in self._roofline_data_per_workload.get( workload_path, pd.DataFrame() ).itertuples(): - for kernel_name in kernel_objs.keys(): - metric_obj = orm.Metric( - name=metric.name, - metric_id=metric.metric_id, - description=metric.description, - unit=metric.unit, - table_name=metric.table_name, - sub_table_name=metric.sub_table_name, - kernel=kernel_objs[kernel_name], + if roofline_data.kernel_name not in kernel_objs: + console_warning( + f"Kernel {roofline_data.kernel_name} from roofline data " + "not found in dispatch data. Skipping roofline entry." ) - Database.get_session().add(metric_obj) + continue + Database.get_session().add( + orm.RooflineData( + total_flops=roofline_data.total_flops, + l1_cache_data=roofline_data.l1_cache_data, + l2_cache_data=roofline_data.l2_cache_data, + hbm_cache_data=roofline_data.hbm_cache_data, + kernel=kernel_objs[roofline_data.kernel_name], + ) + ) - # Direct lookup instead of iterating through all values - key = (metric.metric_id, kernel_name) - for value in values_grouped.get(key, []): - Database.get_session().add( - orm.Value( - metric=metric_obj, - value_name=value.value_name, - value=value.value, - ) + # Add pc sampling data + for pc_sample in self._pc_sampling_data_per_workload.get( + workload_path, pd.DataFrame() + ).itertuples(): + if pc_sample.kernel_name not in kernel_objs: + console_warning( + f"Kernel {pc_sample.kernel_name} from PC sampling data " + "not found in dispatch data. Skipping PC sampling entry." + ) + continue + Database.get_session().add( + orm.PCsampling( + source=pc_sample.source_line, + instruction=pc_sample.instruction, + count=pc_sample.count, + offset=pc_sample.offset, + count_issue=pc_sample.count_issued, + count_stall=pc_sample.count_stalled, + stall_reason=pc_sample.stall_reason, + kernel=kernel_objs[pc_sample.kernel_name], + ) + ) + + # Add metrics and values - iterate on values, create metrics as needed + metrics_info_dict = { + row.metric_id: row + for row in self._metrics_info_data_per_workload.get( + workload_path, pd.DataFrame() + ).itertuples() + } + metric_objs: dict[str, orm.MetricDefinition] = {} + + for value in self._values_data_per_workload.get( + workload_path, pd.DataFrame() + ).itertuples(): + # Check if kernel exists + if value.kernel_name not in kernel_objs: + console_warning( + f"Kernel {value.kernel_name} from values data " + "not found in dispatch data. Skipping metric value." + ) + continue + + # Create or reuse metric object + if value.metric_id not in metric_objs: + # Fetch metric info + if value.metric_id not in metrics_info_dict: + console_warning( + f"Metric {value.metric_id} from values data " + "not found in metrics info. Skipping metric value." ) + continue + metric_info = metrics_info_dict[value.metric_id] + metric_objs[value.metric_id] = orm.MetricDefinition( + name=metric_info.name, + metric_id=metric_info.metric_id, + description=metric_info.description, + unit=metric_info.unit, + table_name=metric_info.table_name, + sub_table_name=metric_info.sub_table_name, + workload=workload_obj, + ) + Database.get_session().add(metric_objs[value.metric_id]) + # Add value + Database.get_session().add( + orm.MetricValue( + metric=metric_objs[value.metric_id], + kernel=kernel_objs[value.kernel_name], + value_name=value.value_name, + value=value.value, + ) + ) + + # Add metadata version = get_version(rocprof_compute_home) Database.get_session().add( orm.Metadata( diff --git a/projects/rocprofiler-compute/src/utils/analysis_orm.py b/projects/rocprofiler-compute/src/utils/analysis_orm.py index f2315fc768..76a9ff3c08 100644 --- a/projects/rocprofiler-compute/src/utils/analysis_orm.py +++ b/projects/rocprofiler-compute/src/utils/analysis_orm.py @@ -45,7 +45,7 @@ from sqlalchemy.sql import Select from utils.logger import console_debug, console_error PREFIX = "compute_" -SCHEMA_VERSION = "1.1.0" +SCHEMA_VERSION = "1.2.0" Base = declarative_base() @@ -63,18 +63,16 @@ class Workload(Base): # Workload can have multiple kernels kernels = relationship("Kernel", back_populates="workload") - # Workload can have multiple roofline data points - roofline_data_points = relationship("RooflineData", back_populates="workload") - # Workload can have multiple pc_sampling values - pc_sampling_values = relationship("PCsampling", back_populates="workload") + # Workload can have multiple metric definitions + metric_definitions = relationship("MetricDefinition", back_populates="workload") -class Metric(Base): - __tablename__ = f"{PREFIX}metric" +class MetricDefinition(Base): + __tablename__ = f"{PREFIX}metric_definition" metric_uuid = Column(Integer, primary_key=True) - kernel_uuid = Column( - Integer, ForeignKey(f"{PREFIX}kernel.kernel_uuid"), nullable=False + workload_id = Column( + Integer, ForeignKey(f"{PREFIX}workload.workload_id"), nullable=False ) name = Column(String) # e.g. Wavefronts Num metric_id = Column(String) # e.g. 4.1.3 @@ -83,27 +81,26 @@ class Metric(Base): sub_table_name = Column(String) # e.g. Wavefront stats unit = Column(String) # e.g. Gbps - # Metric can have one kernel - kernel = relationship("Kernel", back_populates="metrics") - # Metric can have multiple values - values = relationship("Value", back_populates="metric") + # Metric can have one workload + workload = relationship("Workload", back_populates="metric_definitions") + # Metric can have multiple metric values + metric_values = relationship("MetricValue", back_populates="metric") class RooflineData(Base): __tablename__ = f"{PREFIX}roofline_data" roofline_uuid = Column(Integer, primary_key=True) - workload_id = Column( - Integer, ForeignKey(f"{PREFIX}workload.workload_id"), nullable=False + kernel_uuid = Column( + Integer, ForeignKey(f"{PREFIX}kernel.kernel_uuid"), nullable=False ) - kernel_name = Column(String) total_flops = Column(Float) l1_cache_data = Column(Float) l2_cache_data = Column(Float) hbm_cache_data = Column(Float) - # Roofline data point can have one workload - workload = relationship("Workload", back_populates="roofline_data_points") + # Roofline data point can have one kernel + kernel = relationship("Kernel", back_populates="roofline_data_points") class Dispatch(Base): @@ -135,42 +132,50 @@ class Kernel(Base): workload = relationship("Workload", back_populates="kernels") # Kernel can have multiple dispatches dispatches = relationship("Dispatch", back_populates="kernel") - # Kernel can have multiple metrics - metrics = relationship("Metric", back_populates="kernel") + # Kernel can have multiple metric values + metric_values = relationship("MetricValue", back_populates="kernel") + # Kernel can have multiple roofline data points + roofline_data_points = relationship("RooflineData", back_populates="kernel") + # Kernel can have multiple pc_sampling values + pc_sampling_values = relationship("PCsampling", back_populates="kernel") class PCsampling(Base): __tablename__ = f"{PREFIX}pcsampling" pc_sampling_uuid = Column(Integer, primary_key=True) - workload_id = Column( - Integer, ForeignKey(f"{PREFIX}workload.workload_id"), nullable=False + kernel_uuid = Column( + Integer, ForeignKey(f"{PREFIX}kernel.kernel_uuid"), nullable=False ) source = Column(String) instruction = Column(String) count = Column(Integer) - kernel_name = Column(String) offset = Column(Integer) count_issue = Column(Integer) count_stall = Column(Integer) stall_reason = Column(JSON) - # PCsampling can have one workload - workload = relationship("Workload", back_populates="pc_sampling_values") + # PCsampling can have one kernel + kernel = relationship("Kernel", back_populates="pc_sampling_values") -class Value(Base): - __tablename__ = f"{PREFIX}value" +class MetricValue(Base): + __tablename__ = f"{PREFIX}metric_value" value_uuid = Column(Integer, primary_key=True) metric_uuid = Column( - Integer, ForeignKey(f"{PREFIX}metric.metric_uuid"), nullable=False + Integer, ForeignKey(f"{PREFIX}metric_definition.metric_uuid"), nullable=False + ) + kernel_uuid = Column( + Integer, ForeignKey(f"{PREFIX}kernel.kernel_uuid"), nullable=False ) value_name = Column(String) # e.g. min, max, avg value = Column(Float) # e.g. 123.45 # Value can have one metric - metric = relationship("Metric", back_populates="values") + metric = relationship("MetricDefinition", back_populates="metric_values") + # Value can have one kernel + kernel = relationship("Kernel", back_populates="metric_values") class Metadata(Base): @@ -250,11 +255,20 @@ def get_views() -> list[TextClause]: views: dict[str, Select[Any]] = { "kernel_view": select( + Kernel.kernel_uuid.label("kernel_uuid"), + Kernel.workload_id.label("workload_id"), + Workload.name.label("workload_name"), Kernel.kernel_name, func.count(Dispatch.dispatch_id).label("dispatch_count"), func.sum(Dispatch.end_timestamp - Dispatch.start_timestamp).label( "duration_ns_sum" ), + func.min(Dispatch.end_timestamp - Dispatch.start_timestamp).label( + "duration_ns_min" + ), + func.max(Dispatch.end_timestamp - Dispatch.start_timestamp).label( + "duration_ns_max" + ), median_calc.c.duration_ns_median, func.avg(Dispatch.end_timestamp - Dispatch.start_timestamp).label( "duration_ns_mean" @@ -262,24 +276,31 @@ def get_views() -> list[TextClause]: ) .select_from(Dispatch) .join(Kernel, Dispatch.kernel_uuid == Kernel.kernel_uuid) + .join(Workload, Kernel.workload_id == Workload.workload_id) .join(median_calc.subquery(), Kernel.kernel_name == median_calc.c.kernel_name) - .group_by(Kernel.kernel_name), + .group_by( + Kernel.kernel_uuid, Kernel.workload_id, Workload.name, Kernel.kernel_name + ), "metric_view": select( + Workload.workload_id.label("workload_id"), Workload.name.label("workload_name"), + Kernel.kernel_uuid.label("kernel_uuid"), Kernel.kernel_name, - Metric.name.label("metric_name"), - Metric.metric_id, - Metric.description, - Metric.table_name, - Metric.sub_table_name, - Metric.unit, - Value.value_name, - Value.value, + MetricDefinition.metric_uuid.label("metric_uuid"), + MetricDefinition.name.label("metric_name"), + MetricDefinition.metric_id, + MetricDefinition.description, + MetricDefinition.table_name, + MetricDefinition.sub_table_name, + MetricDefinition.unit, + MetricValue.value_uuid.label("value_uuid"), + MetricValue.value_name, + MetricValue.value, ) - .select_from(Metric) - .join(Kernel, Metric.kernel_uuid == Kernel.kernel_uuid) - .join(Value, Metric.metric_uuid == Value.metric_uuid) - .join(Workload, Kernel.workload_id == Workload.workload_id), + .select_from(MetricDefinition) + .join(Workload, MetricDefinition.workload_id == Workload.workload_id) + .join(MetricValue, MetricDefinition.metric_uuid == MetricValue.metric_uuid) + .join(Kernel, MetricValue.kernel_uuid == Kernel.kernel_uuid), } return [ diff --git a/projects/rocprofiler-compute/tests/test_profile_general.py b/projects/rocprofiler-compute/tests/test_profile_general.py index 4b685e6dde..97488141df 100644 --- a/projects/rocprofiler-compute/tests/test_profile_general.py +++ b/projects/rocprofiler-compute/tests/test_profile_general.py @@ -989,19 +989,19 @@ def test_analyze_rocpd( Dispatch, Kernel, Metadata, - Metric, + MetricDefinition, + MetricValue, RooflineData, - Value, Workload, ) table_name_map = { "compute_workload": Workload, - "compute_metric": Metric, + "compute_metric_definition": MetricDefinition, "compute_roofline_data": RooflineData, "compute_dispatch": Dispatch, "compute_kernel": Kernel, - "compute_value": Value, + "compute_metric_value": MetricValue, "compute_metadata": Metadata, } From 1c5aa2d4e748771230138fda1d65b1a28efa4be6 Mon Sep 17 00:00:00 2001 From: SakaSitharammurthy Date: Tue, 20 Jan 2026 02:26:59 +0530 Subject: [PATCH 12/21] [SWDEV-567099] Updated 'amdsmi list --cpu all' command (#2519) Signed-off-by: Saka, Sitharam Murthy --- projects/amdsmi/amdsmi_cli/amdsmi_commands.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/projects/amdsmi/amdsmi_cli/amdsmi_commands.py b/projects/amdsmi/amdsmi_cli/amdsmi_commands.py index acee11a3f1..ee822e16c6 100644 --- a/projects/amdsmi/amdsmi_cli/amdsmi_commands.py +++ b/projects/amdsmi/amdsmi_cli/amdsmi_commands.py @@ -226,6 +226,12 @@ class AMDSMICommands(): # Set args.* to passed in arguments if gpu: args.gpu = gpu + + cpu_attributes = ["cpu"] + for attr in cpu_attributes: + if hasattr(args, 'cpu') and getattr(args, 'cpu'): + print("N/A") + return # Handle No GPU passed if args.gpu == None: From dd149d3957f9598d64473f1ddf54148c4cc13fe8 Mon Sep 17 00:00:00 2001 From: abchoudh-amd Date: Tue, 20 Jan 2026 02:30:14 +0530 Subject: [PATCH 13/21] [rocprofiler-compute] Support new attach/detach API (#2642) * Removed attach tool library path * Support new attach/detach API * New attach/detach API was introduced in https://github.com/ROCm/rocm-systems/pull/1653 * Provide backward compatibility with old api * Stabilize attach/detach tests by adding sleep to help workload get ready for attachment * Fix typo in test name --------- Co-authored-by: Vignesh Edithal Co-authored-by: Fei Zheng <44449748+feizheng10@users.noreply.github.com> --- .../profiler_rocprofiler_sdk.py | 1 - .../rocprofiler-compute/src/utils/utils.py | 139 ++++++++++++------ .../tests/test_profile_general.py | 8 +- 3 files changed, 102 insertions(+), 46 deletions(-) diff --git a/projects/rocprofiler-compute/src/rocprof_compute_profile/profiler_rocprofiler_sdk.py b/projects/rocprofiler-compute/src/rocprof_compute_profile/profiler_rocprofiler_sdk.py index f976c99d0d..542ec04619 100644 --- a/projects/rocprofiler-compute/src/rocprof_compute_profile/profiler_rocprofiler_sdk.py +++ b/projects/rocprofiler-compute/src/rocprof_compute_profile/profiler_rocprofiler_sdk.py @@ -92,7 +92,6 @@ class rocprofiler_sdk_profiler(RocProfCompute_Base): / "librocprofiler-sdk-rocattach.so" ) options.update({ - "ROCPROF_ATTACH_TOOL_LIBRARY": rocprofiler_sdk_tool_path, "ROCPROF_ATTACH_LIBRARY": rocprofiler_attach_library_path, "ROCPROF_ATTACH_PID": args.attach_pid, }) diff --git a/projects/rocprofiler-compute/src/utils/utils.py b/projects/rocprofiler-compute/src/utils/utils.py index c85471edae..6d51d972ff 100644 --- a/projects/rocprofiler-compute/src/utils/utils.py +++ b/projects/rocprofiler-compute/src/utils/utils.py @@ -235,6 +235,101 @@ def detect_rocprof(args: argparse.Namespace) -> str: return rocprof_cmd +def perform_attach_detach(new_env: dict[str, str], options: dict[str, Any]) -> None: + @contextmanager + def temporary_env(env_vars: dict[str, str]) -> Generator[None, None, None]: + """ + Temporarily change the environment variable of this application. + """ + original_env = os.environ.copy() + os.environ.update({k: str(v) for k, v in env_vars.items()}) + try: + yield + finally: + os.environ.clear() + os.environ.update(original_env) + + with temporary_env(new_env): + libname = options["ROCPROF_ATTACH_LIBRARY"] + + try: + c_lib = ctypes.CDLL(libname) + if c_lib is None: + console_error(f"Error opening {libname}") + except Exception as e: + console_error(f"Error loading {libname}: {e}") + + # Set argument and return types for attach/detach functions + try: + # old attach/detach API + c_lib.attach.argtypes = [ctypes.c_uint] + except Exception as e: + console_debug( + "Error setting old attach/detach API argument " + f"types: {e}, trying new API" + ) + try: + # new attach/detach API + c_lib.rocattach_attach.restype = ctypes.c_int + c_lib.rocattach_attach.argtypes = [ctypes.c_int] + c_lib.rocattach_detach.restype = ctypes.c_int + c_lib.rocattach_detach.argtypes = [ctypes.c_int] + except Exception as e: + console_error( + f"Error setting attach/detach function argument types: {e}" + ) + + pid = options["ROCPROF_ATTACH_PID"] + if pid is None: + console_error("Mode of attach/detach must have setup for process ID") + + try: + # old attach/detach API + c_lib.attach(int(pid)) + except Exception as e: + console_debug(f"Error attaching with old API: {e}, trying new API") + try: + # new attach/detach API + attach_status = c_lib.rocattach_attach(int(pid)) + if attach_status != 0: + console_error( + f"Error attaching to process {pid}, " + f"rocattach_attach returned {attach_status}" + ) + except Exception as e: + console_error(f"Error attaching to process {pid}: {e}") + + duration = os.environ.get("ROCPROF_ATTACH_DURATION", None) + if duration is None: + console_log( + f"\033[93mAttach to process with ID {pid} is successful, " + "Press Enter to detach...\033[0m" + ) + input() + else: + console_log( + f"\033[93mAttach to process with ID {pid} is successful, " + f"detach will happen in {duration} milliseconds...\033[0m" + ) + time.sleep(int(duration) / 1000) + + try: + # old attach/detach API + c_lib.detach(int(pid)) + except Exception as e: + console_debug(f"Error detaching with old API: {e}, trying new API") + try: + # new attach/detach API + detach_status = c_lib.rocattach_detach(int(pid)) + if detach_status != 0: + console_error( + f"Error detaching from process {pid}, " + f"rocattach_detach returned {detach_status}" + ) + except Exception as e: + console_error(f"Error detaching from process {pid}: {e}") + + def capture_subprocess_output( subprocess_args: list[str], new_env: Optional[dict[str, str]] = None, @@ -788,49 +883,7 @@ def run_prof( console_debug(f"rocprof sdk env vars: {new_env}") if is_mode_live_attach: - - @contextmanager - def temporary_env(env_vars: dict[str, str]) -> Generator[None, None, None]: - """ - Temporarily change the environment variable of this application. - """ - original_env = os.environ.copy() - os.environ.update({k: str(v) for k, v in env_vars.items()}) - try: - yield - finally: - os.environ.clear() - os.environ.update(original_env) - - with temporary_env(new_env): - libname = options["ROCPROF_ATTACH_LIBRARY"] - c_lib = ctypes.CDLL(libname) - if c_lib is None: - console_error(f"Error opening {libname}") - c_lib.attach.argtypes = [ctypes.c_uint] - - pid = options["ROCPROF_ATTACH_PID"] - if pid is None: - console_error( - "Mode of attach/detach must have setup for process ID" - ) - - c_lib.attach(int(pid)) - duration = os.environ.get("ROCPROF_ATTACH_DURATION", None) - if duration is None: - console_log( - f"\033[93mAttach to process with ID {pid} is successful, " - "Press Enter to detach...\033[0m" - ) - input() - else: - console_log( - f"\033[93mAttach to process with ID {pid} is successful, " - f"detach will happen in {duration} milliseconds...\033[0m" - ) - time.sleep(int(duration) / 1000) - c_lib.detach(int(pid)) - + perform_attach_detach(new_env, options) else: if app_cmd is None: console_error( diff --git a/projects/rocprofiler-compute/tests/test_profile_general.py b/projects/rocprofiler-compute/tests/test_profile_general.py index 97488141df..fcaf05a130 100644 --- a/projects/rocprofiler-compute/tests/test_profile_general.py +++ b/projects/rocprofiler-compute/tests/test_profile_general.py @@ -29,6 +29,7 @@ import re import sqlite3 import subprocess import sys +import time from pathlib import Path import numpy as np @@ -2268,6 +2269,7 @@ def test_live_attach_detach_block(binary_handler_profile_rocprof_compute): try: # Start workload process_workload = subprocess.Popen(config["app_hip_dynamic_shared"], env=env) + time.sleep(5) # Give workload time to start attach_detach = { "attach_pid": process_workload.pid, @@ -2316,8 +2318,9 @@ def test_live_attach_detach_block_thread_sleep(binary_handler_profile_rocprof_co try: # Start workload with sleep mode enabled process_workload = subprocess.Popen( - [config["app_hip_dynamic_shared"], "--enable-sleep"], env=env + [*config["app_hip_dynamic_shared"], "--enable-sleep"], env=env ) + time.sleep(5) # Give workload time to start attach_detach = { "attach_pid": process_workload.pid, @@ -2358,7 +2361,7 @@ def test_live_attach_detach_block_thread_sleep(binary_handler_profile_rocprof_co @pytest.mark.live_attach_detach -def test_live_attach_detach_singlepath_launch_stats( +def test_live_attach_detach_singlepass_launch_stats( binary_handler_profile_rocprof_compute, ): options = ["--set", "launch_stats"] @@ -2374,6 +2377,7 @@ def test_live_attach_detach_singlepath_launch_stats( try: # Start workload process_workload = subprocess.Popen(config["app_hip_dynamic_shared"], env=env) + time.sleep(5) # Give workload time to start attach_detach = { "attach_pid": process_workload.pid, From 9f37cd6309a12045e1efd0691bf5a20887cb87ca Mon Sep 17 00:00:00 2001 From: marandje Date: Mon, 19 Jan 2026 22:10:15 +0100 Subject: [PATCH 14/21] SWDEV-1 - Fix hipMemPoolTrimTo failing tests (#2628) --- projects/hip-tests/catch/unit/memory/hipMemPoolTrimTo.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/hip-tests/catch/unit/memory/hipMemPoolTrimTo.cc b/projects/hip-tests/catch/unit/memory/hipMemPoolTrimTo.cc index dde9bd4aaa..9315b98565 100644 --- a/projects/hip-tests/catch/unit/memory/hipMemPoolTrimTo.cc +++ b/projects/hip-tests/catch/unit/memory/hipMemPoolTrimTo.cc @@ -177,8 +177,8 @@ static bool checkhipMemPoolTrimTo(hipStream_t stream, int N, int dev = 0) { testObj.transferFromMempool(stream); testObj.freeDevBuf(stream); // verify and validate - REQUIRE(true == testObj.validateResult()); HIP_CHECK(hipStreamSynchronize(stream)); + REQUIRE(true == testObj.validateResult()); } HIP_CHECK(hipMemPoolDestroy(mem_pool)); return true; From 99c3a06f4e68007a4217213089bd20864f7838ac Mon Sep 17 00:00:00 2001 From: Karthik Jayaprakash <54370791+kjayapra-amd@users.noreply.github.com> Date: Mon, 19 Jan 2026 16:16:14 -0500 Subject: [PATCH 15/21] SWDEV-549518 - Enable logging dynamically through HIP APIS. (#1079) * SWDEV-549518 - Enable logging dynamically through HIP APIS. * SWDEV-549518 - Adding ROCProfiler related new API changes. * rocprofiler-sdk changes for hip api additions. --------- Co-authored-by: Venkateshwar Reddy Kandula Co-authored-by: jainprad <92369414+jainprad@users.noreply.github.com> --- .../include/hip/amd_detail/hip_api_trace.hpp | 12 +- .../include/hip/amd_detail/hip_prof_str.h | 52 +++++- projects/clr/hipamd/src/CMakeLists.txt | 1 + projects/clr/hipamd/src/amdhip.def | 3 + projects/clr/hipamd/src/hip_api_trace.cpp | 14 +- projects/clr/hipamd/src/hip_hcc.map.in | 3 + projects/clr/hipamd/src/hip_log.cpp | 31 ++++ projects/clr/hipamd/src/hip_platform.hpp | 18 +- .../clr/hipamd/src/hip_table_interface.cpp | 9 + .../hipTestMain/config/config_amd_windows | 2 + .../catch/unit/errorHandling/CMakeLists.txt | 1 + .../catch/unit/errorHandling/OutCapture.hh | 134 +++++++++++++++ .../unit/errorHandling/hipDynamicLogging.cc | 156 ++++++++++++++++++ projects/hip/include/hip/hip_runtime_api.h | 39 +++++ .../rocprofiler-sdk/cxx/enum_string.hpp | 7 + .../include/rocprofiler-sdk/hip/api_args.h | 20 +++ .../rocprofiler-sdk/hip/runtime_api_id.h | 5 + .../source/lib/rocprofiler-sdk/hip/abi.cpp | 8 + .../lib/rocprofiler-sdk/hip/hip.def.cpp | 5 + 19 files changed, 514 insertions(+), 6 deletions(-) create mode 100644 projects/clr/hipamd/src/hip_log.cpp create mode 100644 projects/hip-tests/catch/unit/errorHandling/OutCapture.hh create mode 100644 projects/hip-tests/catch/unit/errorHandling/hipDynamicLogging.cc diff --git a/projects/clr/hipamd/include/hip/amd_detail/hip_api_trace.hpp b/projects/clr/hipamd/include/hip/amd_detail/hip_api_trace.hpp index f1864eaca4..7845b69e8a 100644 --- a/projects/clr/hipamd/include/hip/amd_detail/hip_api_trace.hpp +++ b/projects/clr/hipamd/include/hip/amd_detail/hip_api_trace.hpp @@ -63,7 +63,7 @@ #define HIP_API_TABLE_STEP_VERSION 0 #define HIP_COMPILER_API_TABLE_STEP_VERSION 0 #define HIP_TOOLS_API_TABLE_STEP_VERSION 0 -#define HIP_RUNTIME_API_TABLE_STEP_VERSION 20 +#define HIP_RUNTIME_API_TABLE_STEP_VERSION 21 // HIP API interface // HIP compiler dispatch functions @@ -1113,6 +1113,9 @@ typedef hipError_t (*t_hipKernelGetLibrary)(hipLibrary_t* library, hipKernel_t k typedef hipError_t (*t_hipKernelGetName)(const char** name, hipKernel_t kernel); typedef hipError_t (*t_hipGetProcAddress_spt)(const char* symbol, void** pfn, int hipVersion, uint64_t flags, hipDriverProcAddressQueryResult* symbolStatus); +typedef hipError_t (*t_hipExtDisableLogging)(); +typedef hipError_t (*t_hipExtEnableLogging)(); +typedef hipError_t (*t_hipExtSetLoggingParams)(size_t log_level, size_t log_size, size_t log_mask); typedef hipError_t (*t_hipKernelGetParamInfo)(hipKernel_t kernel, size_t paramIndex, size_t* paramOffset, size_t* paramSize); @@ -1707,8 +1710,13 @@ struct HipDispatchTable { // HIP_RUNTIME_API_TABLE_STEP_VERSION == 20 t_hipKernelGetParamInfo hipKernelGetParamInfo_fn; - // DO NOT EDIT ABOVE! // HIP_RUNTIME_API_TABLE_STEP_VERSION == 21 + t_hipExtDisableLogging hipExtDisableLogging_fn; + t_hipExtEnableLogging hipExtEnableLogging_fn; + t_hipExtSetLoggingParams hipExtSetLoggingParams_fn; + + // DO NOT EDIT ABOVE! + // HIP_RUNTIME_API_TABLE_STEP_VERSION == 22 // ******************************************************************************************* // // diff --git a/projects/clr/hipamd/include/hip/amd_detail/hip_prof_str.h b/projects/clr/hipamd/include/hip/amd_detail/hip_prof_str.h index 7aef3e7f52..2dc1a0d3b2 100644 --- a/projects/clr/hipamd/include/hip/amd_detail/hip_prof_str.h +++ b/projects/clr/hipamd/include/hip/amd_detail/hip_prof_str.h @@ -468,7 +468,10 @@ enum hip_api_id_t { HIP_API_ID_hipKernelGetName = 448, HIP_API_ID_hipOccupancyAvailableDynamicSMemPerBlock = 449, HIP_API_ID_hipKernelGetParamInfo = 450, - HIP_API_ID_LAST = 450, + HIP_API_ID_hipExtDisableLogging = 451, + HIP_API_ID_hipExtEnableLogging = 452, + HIP_API_ID_hipExtSetLoggingParams = 453, + HIP_API_ID_LAST = 453, HIP_API_ID_hipChooseDevice = HIP_API_ID_CONCAT(HIP_API_ID_,hipChooseDevice), HIP_API_ID_hipGetDeviceProperties = HIP_API_ID_CONCAT(HIP_API_ID_,hipGetDeviceProperties), @@ -590,12 +593,15 @@ static inline const char* hip_api_name(const uint32_t id) { case HIP_API_ID_hipEventRecord: return "hipEventRecord"; case HIP_API_ID_hipEventRecordWithFlags: return "hipEventRecordWithFlags"; case HIP_API_ID_hipEventSynchronize: return "hipEventSynchronize"; + case HIP_API_ID_hipExtDisableLogging: return "hipExtDisableLogging"; + case HIP_API_ID_hipExtEnableLogging: return "hipExtEnableLogging"; case HIP_API_ID_hipExtGetLastError: return "hipExtGetLastError"; case HIP_API_ID_hipExtGetLinkTypeAndHopCount: return "hipExtGetLinkTypeAndHopCount"; case HIP_API_ID_hipExtLaunchKernel: return "hipExtLaunchKernel"; case HIP_API_ID_hipExtLaunchMultiKernelMultiDevice: return "hipExtLaunchMultiKernelMultiDevice"; case HIP_API_ID_hipExtMallocWithFlags: return "hipExtMallocWithFlags"; case HIP_API_ID_hipExtModuleLaunchKernel: return "hipExtModuleLaunchKernel"; + case HIP_API_ID_hipExtSetLoggingParams: return "hipExtSetLoggingParams"; case HIP_API_ID_hipExtStreamCreateWithCUMask: return "hipExtStreamCreateWithCUMask"; case HIP_API_ID_hipExtStreamGetCUMask: return "hipExtStreamGetCUMask"; case HIP_API_ID_hipExternalMemoryGetMappedBuffer: return "hipExternalMemoryGetMappedBuffer"; @@ -1034,12 +1040,15 @@ static inline uint32_t hipApiIdByName(const char* name) { if (strcmp("hipEventRecord", name) == 0) return HIP_API_ID_hipEventRecord; if (strcmp("hipEventRecordWithFlags", name) == 0) return HIP_API_ID_hipEventRecordWithFlags; if (strcmp("hipEventSynchronize", name) == 0) return HIP_API_ID_hipEventSynchronize; + if (strcmp("hipExtDisableLogging", name) == 0) return HIP_API_ID_hipExtDisableLogging; + if (strcmp("hipExtEnableLogging", name) == 0) return HIP_API_ID_hipExtEnableLogging; if (strcmp("hipExtGetLastError", name) == 0) return HIP_API_ID_hipExtGetLastError; if (strcmp("hipExtGetLinkTypeAndHopCount", name) == 0) return HIP_API_ID_hipExtGetLinkTypeAndHopCount; if (strcmp("hipExtLaunchKernel", name) == 0) return HIP_API_ID_hipExtLaunchKernel; if (strcmp("hipExtLaunchMultiKernelMultiDevice", name) == 0) return HIP_API_ID_hipExtLaunchMultiKernelMultiDevice; if (strcmp("hipExtMallocWithFlags", name) == 0) return HIP_API_ID_hipExtMallocWithFlags; if (strcmp("hipExtModuleLaunchKernel", name) == 0) return HIP_API_ID_hipExtModuleLaunchKernel; + if (strcmp("hipExtSetLoggingParams", name) == 0) return HIP_API_ID_hipExtSetLoggingParams; if (strcmp("hipExtStreamCreateWithCUMask", name) == 0) return HIP_API_ID_hipExtStreamCreateWithCUMask; if (strcmp("hipExtStreamGetCUMask", name) == 0) return HIP_API_ID_hipExtStreamGetCUMask; if (strcmp("hipExternalMemoryGetMappedBuffer", name) == 0) return HIP_API_ID_hipExternalMemoryGetMappedBuffer; @@ -1851,6 +1860,11 @@ typedef struct hip_api_data_s { hipEvent_t stopEvent; unsigned int flags; } hipExtModuleLaunchKernel; + struct { + size_t log_level; + size_t log_size; + size_t log_mask; + } hipExtSetLoggingParams; struct { hipStream_t* stream; hipStream_t stream__val; @@ -4484,6 +4498,12 @@ typedef struct hip_api_data_s { #define INIT_hipEventSynchronize_CB_ARGS_DATA(cb_data) { \ cb_data.args.hipEventSynchronize.event = (hipEvent_t)event; \ }; +// hipExtDisableLogging[] +#define INIT_hipExtDisableLogging_CB_ARGS_DATA(cb_data) { \ +}; +// hipExtEnableLogging[] +#define INIT_hipExtEnableLogging_CB_ARGS_DATA(cb_data) { \ +}; // hipExtGetLastError[] #define INIT_hipExtGetLastError_CB_ARGS_DATA(cb_data) { \ }; @@ -4535,6 +4555,12 @@ typedef struct hip_api_data_s { cb_data.args.hipExtModuleLaunchKernel.stopEvent = (hipEvent_t)stopEvent; \ cb_data.args.hipExtModuleLaunchKernel.flags = (unsigned int)flags; \ }; +// hipExtSetLoggingParams[('size_t', 'log_level'), ('size_t', 'log_size'), ('size_t', 'log_mask')] +#define INIT_hipExtSetLoggingParams_CB_ARGS_DATA(cb_data) { \ + cb_data.args.hipExtSetLoggingParams.log_level = (size_t)log_level; \ + cb_data.args.hipExtSetLoggingParams.log_size = (size_t)log_size; \ + cb_data.args.hipExtSetLoggingParams.log_mask = (size_t)log_mask; \ +}; // hipExtStreamCreateWithCUMask[('hipStream_t*', 'stream'), ('unsigned int', 'cuMaskSize'), ('const unsigned int*', 'cuMask')] #define INIT_hipExtStreamCreateWithCUMask_CB_ARGS_DATA(cb_data) { \ cb_data.args.hipExtStreamCreateWithCUMask.stream = (hipStream_t*)stream; \ @@ -7125,6 +7151,12 @@ static inline void hipApiArgsInit(hip_api_id_t id, hip_api_data_t* data) { // hipEventSynchronize[('hipEvent_t', 'event')] case HIP_API_ID_hipEventSynchronize: break; +// hipExtDisableLogging[] + case HIP_API_ID_hipExtDisableLogging: + break; +// hipExtEnableLogging[] + case HIP_API_ID_hipExtEnableLogging: + break; // hipExtGetLastError[] case HIP_API_ID_hipExtGetLastError: break; @@ -7150,6 +7182,9 @@ static inline void hipApiArgsInit(hip_api_id_t id, hip_api_data_t* data) { if (data->args.hipExtModuleLaunchKernel.kernelParams) data->args.hipExtModuleLaunchKernel.kernelParams__val = *(data->args.hipExtModuleLaunchKernel.kernelParams); if (data->args.hipExtModuleLaunchKernel.extra) data->args.hipExtModuleLaunchKernel.extra__val = *(data->args.hipExtModuleLaunchKernel.extra); break; +// hipExtSetLoggingParams[('size_t', 'log_level'), ('size_t', 'log_size'), ('size_t', 'log_mask')] + case HIP_API_ID_hipExtSetLoggingParams: + break; // hipExtStreamCreateWithCUMask[('hipStream_t*', 'stream'), ('unsigned int', 'cuMaskSize'), ('const unsigned int*', 'cuMask')] case HIP_API_ID_hipExtStreamCreateWithCUMask: if (data->args.hipExtStreamCreateWithCUMask.stream) data->args.hipExtStreamCreateWithCUMask.stream__val = *(data->args.hipExtStreamCreateWithCUMask.stream); @@ -9124,6 +9159,14 @@ static inline const char* hipApiString(hip_api_id_t id, const hip_api_data_t* da oss << "event="; roctracer::hip_support::detail::operator<<(oss, data->args.hipEventSynchronize.event); oss << ")"; break; + case HIP_API_ID_hipExtDisableLogging: + oss << "hipExtDisableLogging("; + oss << ")"; + break; + case HIP_API_ID_hipExtEnableLogging: + oss << "hipExtEnableLogging("; + oss << ")"; + break; case HIP_API_ID_hipExtGetLastError: oss << "hipExtGetLastError("; oss << ")"; @@ -9188,6 +9231,13 @@ static inline const char* hipApiString(hip_api_id_t id, const hip_api_data_t* da oss << ", flags="; roctracer::hip_support::detail::operator<<(oss, data->args.hipExtModuleLaunchKernel.flags); oss << ")"; break; + case HIP_API_ID_hipExtSetLoggingParams: + oss << "hipExtSetLoggingParams("; + oss << "log_level="; roctracer::hip_support::detail::operator<<(oss, data->args.hipExtSetLoggingParams.log_level); + oss << ", log_size="; roctracer::hip_support::detail::operator<<(oss, data->args.hipExtSetLoggingParams.log_size); + oss << ", log_mask="; roctracer::hip_support::detail::operator<<(oss, data->args.hipExtSetLoggingParams.log_mask); + oss << ")"; + break; case HIP_API_ID_hipExtStreamCreateWithCUMask: oss << "hipExtStreamCreateWithCUMask("; if (data->args.hipExtStreamCreateWithCUMask.stream == NULL) oss << "stream=NULL"; diff --git a/projects/clr/hipamd/src/CMakeLists.txt b/projects/clr/hipamd/src/CMakeLists.txt index aa8d307688..0f7c537ba4 100644 --- a/projects/clr/hipamd/src/CMakeLists.txt +++ b/projects/clr/hipamd/src/CMakeLists.txt @@ -110,6 +110,7 @@ target_sources(amdhip64 PRIVATE hip_graph.cpp hip_hmm.cpp hip_intercept.cpp + hip_log.cpp hip_memory.cpp hip_mempool.cpp hip_mempool_impl.cpp diff --git a/projects/clr/hipamd/src/amdhip.def b/projects/clr/hipamd/src/amdhip.def index dff046d1ac..9a12cbf080 100644 --- a/projects/clr/hipamd/src/amdhip.def +++ b/projects/clr/hipamd/src/amdhip.def @@ -523,3 +523,6 @@ hipKernelGetName hipOccupancyAvailableDynamicSMemPerBlock hipGetProcAddress_spt hipKernelGetParamInfo +hipExtDisableLogging +hipExtEnableLogging +hipExtSetLoggingParams diff --git a/projects/clr/hipamd/src/hip_api_trace.cpp b/projects/clr/hipamd/src/hip_api_trace.cpp index 6399924ec2..564f0bccea 100644 --- a/projects/clr/hipamd/src/hip_api_trace.cpp +++ b/projects/clr/hipamd/src/hip_api_trace.cpp @@ -885,6 +885,9 @@ hipError_t hipOccupancyAvailableDynamicSMemPerBlock(size_t* dynamicSmemSize, con int numBlocks, int blockSize); hipError_t hipKernelGetParamInfo(hipKernel_t kernel, size_t paramIndex, size_t* paramOffset, size_t* paramSize); +hipError_t hipExtDisableLogging(); +hipError_t hipExtEnableLogging(); +hipError_t hipExtSetLoggingParams(size_t log_level, size_t log_size, size_t log_mask); } // namespace hip namespace hip { @@ -1432,6 +1435,9 @@ void UpdateDispatchTable(HipDispatchTable* ptrDispatchTable) { ptrDispatchTable->hipKernelGetName_fn = hip::hipKernelGetName; ptrDispatchTable->hipOccupancyAvailableDynamicSMemPerBlock_fn = hip::hipOccupancyAvailableDynamicSMemPerBlock; ptrDispatchTable->hipKernelGetParamInfo_fn = hip::hipKernelGetParamInfo; + ptrDispatchTable->hipExtDisableLogging_fn = hip::hipExtDisableLogging; + ptrDispatchTable->hipExtEnableLogging_fn = hip::hipExtEnableLogging; + ptrDispatchTable->hipExtSetLoggingParams_fn = hip::hipExtSetLoggingParams; } #if HIP_ROCPROFILER_REGISTER > 0 @@ -2114,15 +2120,19 @@ HIP_ENFORCE_ABI(HipDispatchTable, hipOccupancyAvailableDynamicSMemPerBlock_fn, 5 HIP_ENFORCE_ABI(HipDispatchTable, hipGetProcAddress_spt_fn, 506); // HIP_RUNTIME_API_TABLE_STEP_VERSION == 20 HIP_ENFORCE_ABI(HipDispatchTable, hipKernelGetParamInfo_fn, 507); +// HIP_RUNTIME_API_TABLE_STEP_VERSION == 21 +HIP_ENFORCE_ABI(HipDispatchTable, hipExtDisableLogging_fn, 508); +HIP_ENFORCE_ABI(HipDispatchTable, hipExtEnableLogging_fn, 509); +HIP_ENFORCE_ABI(HipDispatchTable, hipExtSetLoggingParams_fn, 510); // if HIP_ENFORCE_ABI entries are added for each new function pointer in the table, the number below // will be +1 of the number in the last HIP_ENFORCE_ABI line. E.g.: // // HIP_ENFORCE_ABI(, , 8) // // HIP_ENFORCE_ABI_VERSIONING(
, 9) <- 8 + 1 = 9 -HIP_ENFORCE_ABI_VERSIONING(HipDispatchTable, 508) +HIP_ENFORCE_ABI_VERSIONING(HipDispatchTable, 511) -static_assert(HIP_RUNTIME_API_TABLE_MAJOR_VERSION == 0 && HIP_RUNTIME_API_TABLE_STEP_VERSION == 20, +static_assert(HIP_RUNTIME_API_TABLE_MAJOR_VERSION == 0 && HIP_RUNTIME_API_TABLE_STEP_VERSION == 21, "If you get this error, add new HIP_ENFORCE_ABI(...) code for the new function " "pointers and then update this check so it is true"); #endif diff --git a/projects/clr/hipamd/src/hip_hcc.map.in b/projects/clr/hipamd/src/hip_hcc.map.in index 37437589e8..79c15835a5 100644 --- a/projects/clr/hipamd/src/hip_hcc.map.in +++ b/projects/clr/hipamd/src/hip_hcc.map.in @@ -645,6 +645,9 @@ global: hipOccupancyAvailableDynamicSMemPerBlock; hipGetProcAddress_spt; hipKernelGetParamInfo; + hipExtDisableLogging; + hipExtEnableLogging; + hipExtSetLoggingParams; local: *; } hip_7.1; diff --git a/projects/clr/hipamd/src/hip_log.cpp b/projects/clr/hipamd/src/hip_log.cpp new file mode 100644 index 0000000000..6d43c0dc77 --- /dev/null +++ b/projects/clr/hipamd/src/hip_log.cpp @@ -0,0 +1,31 @@ +#include +#include "hip_internal.hpp" +#include "hip_platform.hpp" + +namespace hip { + +hipError_t hipExtEnableLogging() { + HIP_INIT_API(hipExtEnableLogging); + amd::ScopedLock lock(PlatformState::instance().getLogLock()); + AMD_LOG_LEVEL = PlatformState::instance().log_level_; + AMD_LOG_MASK = PlatformState::instance().log_mask_; + HIP_RETURN(hipSuccess); +} + +hipError_t hipExtDisableLogging() { + HIP_INIT_API(hipExtDisableLogging); + amd::ScopedLock lock(PlatformState::instance().getLogLock()); + AMD_LOG_LEVEL = 0; + HIP_RETURN(hipSuccess); +} + +hipError_t hipExtSetLoggingParams(size_t log_level, size_t log_size, size_t log_mask) { + HIP_INIT_API(hipExtSetLoggingParams, log_level, log_size, log_mask); + amd::ScopedLock lock(PlatformState::instance().getLogLock()); + // Store logging parameters for later activation + PlatformState::instance().log_level_ = log_level; + PlatformState::instance().log_size_ = log_size; + PlatformState::instance().log_mask_ = log_mask; + HIP_RETURN(hipSuccess); +} +} // namespace::hip \ No newline at end of file diff --git a/projects/clr/hipamd/src/hip_platform.hpp b/projects/clr/hipamd/src/hip_platform.hpp index bd714206ef..ba8261f3d2 100644 --- a/projects/clr/hipamd/src/hip_platform.hpp +++ b/projects/clr/hipamd/src/hip_platform.hpp @@ -50,9 +50,12 @@ class PlatformState { // Unique FD Store Lock amd::Monitor ufd_lock_{true}; + // Lock for logging operations + amd::Monitor lg_lock_{true}; + // Singleton object static PlatformState* platform_; - PlatformState() {} + PlatformState() : log_level_(0), log_size_(0), log_mask_(0) {} ~PlatformState() {} public: @@ -113,6 +116,14 @@ class PlatformState { size_t UfdMapSize() const { return ufd_map_.size(); } + // Logging lock accessor + amd::Monitor& getLogLock() { return lg_lock_; } + + // Friend functions for logging access + friend hipError_t hipExtEnableLogging(); + friend hipError_t hipExtDisableLogging(); + friend hipError_t hipExtSetLoggingParams(size_t log_level, size_t log_size, size_t log_mask); + inline bool RegisterLibraryFunction(const hipKernel_t f, const hipLibrary_t l) { amd::ScopedLock lock(lock_); if (library_functions_.find(f) == library_functions_.end()) { @@ -150,5 +161,10 @@ class PlatformState { void* dynamicLibraryHandle_{nullptr}; std::unordered_map library_functions_; + + // Logging state (moved from LoggingInfo singleton) + size_t log_level_; + size_t log_size_; + size_t log_mask_; }; } // namespace hip diff --git a/projects/clr/hipamd/src/hip_table_interface.cpp b/projects/clr/hipamd/src/hip_table_interface.cpp index 443ba81ba5..d8783c9ee0 100644 --- a/projects/clr/hipamd/src/hip_table_interface.cpp +++ b/projects/clr/hipamd/src/hip_table_interface.cpp @@ -2067,4 +2067,13 @@ hipError_t hipKernelGetParamInfo(hipKernel_t kernel, size_t paramIndex, size_t* size_t* paramSize) { return hip::GetHipDispatchTable()->hipKernelGetParamInfo_fn(kernel, paramIndex, paramOffset, paramSize); +} +hipError_t hipExtEnableLogging() { + return hip::GetHipDispatchTable()->hipExtEnableLogging_fn(); +} +hipError_t hipExtDisableLogging() { + return hip::GetHipDispatchTable()->hipExtDisableLogging_fn(); +} +hipError_t hipExtSetLoggingParams(size_t log_level, size_t log_size, size_t log_mask) { + return hip::GetHipDispatchTable()->hipExtSetLoggingParams_fn(log_level, log_size, log_mask); } \ No newline at end of file diff --git a/projects/hip-tests/catch/hipTestMain/config/config_amd_windows b/projects/hip-tests/catch/hipTestMain/config/config_amd_windows index 85e17cd381..24e5cefcf5 100644 --- a/projects/hip-tests/catch/hipTestMain/config/config_amd_windows +++ b/projects/hip-tests/catch/hipTestMain/config/config_amd_windows @@ -752,6 +752,8 @@ #endif "=== Following tests disabled as it should be a local perf test", "Performance_hipExtLaunchKernelGGL_QueryGPUFrequency", + "Unit_hipDynamicLogging_Positive_Basic", + "Unit_hipDynamicLogging_Positive_MultipleEnableDisable", "End of json" ] } diff --git a/projects/hip-tests/catch/unit/errorHandling/CMakeLists.txt b/projects/hip-tests/catch/unit/errorHandling/CMakeLists.txt index b1e9220bfc..873417baf7 100644 --- a/projects/hip-tests/catch/unit/errorHandling/CMakeLists.txt +++ b/projects/hip-tests/catch/unit/errorHandling/CMakeLists.txt @@ -7,6 +7,7 @@ set(TEST_SRC hipDrvGetErrorString.cc hipGetLastError.cc hipPeekAtLastError.cc + hipDynamicLogging.cc ) if(UNIX) diff --git a/projects/hip-tests/catch/unit/errorHandling/OutCapture.hh b/projects/hip-tests/catch/unit/errorHandling/OutCapture.hh new file mode 100644 index 0000000000..febd7e429f --- /dev/null +++ b/projects/hip-tests/catch/unit/errorHandling/OutCapture.hh @@ -0,0 +1,134 @@ +/* +Copyright (c) 2023 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. +*/ + +#pragma once + +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#include +#include +#define dup _dup +#define dup2 _dup2 +#define fd_close _close +#define unlink _unlink +#define STDERR_FD _fileno(stderr) +#define OPEN_FLAGS (_O_WRONLY | _O_CREAT | _O_TRUNC) +#define OPEN_MODE (_S_IREAD | _S_IWRITE) +#define open _open +#else +#include +#define fd_close close +#define STDERR_FD STDERR_FILENO +#define OPEN_FLAGS (O_WRONLY | O_CREAT | O_TRUNC) +#define OPEN_MODE 0644 +#endif + +// Class to capture all stderr output (HIP logging uses stderr) +class OutCapture { +private: + std::stringstream captured_stream_; + std::streambuf* cerr_backup_; + int stderr_backup_; + std::string temp_file_; + + static std::string getTempFilePath() { +#ifdef _WIN32 + char temp_path[MAX_PATH]; + if (GetTempPathA(MAX_PATH, temp_path)) { + return std::string(temp_path) + "hip_stderr_capture.txt"; + } + // Fallback to current directory + return "hip_stderr_capture.txt"; +#else + return "/tmp/hip_stderr_capture.txt"; +#endif + } + +public: + OutCapture() : temp_file_(getTempFilePath()) { + // Backup original cerr stream buffer (HIP logging uses stderr) + cerr_backup_ = std::cerr.rdbuf(); + + // Backup original stderr file descriptor + stderr_backup_ = dup(STDERR_FD); + } + + void startCapture() { + // Clear any previous content + captured_stream_.str(""); + captured_stream_.clear(); + + // Redirect std::cerr to our stringstream + std::cerr.rdbuf(captured_stream_.rdbuf()); + + // Redirect stderr file descriptor to temp file (for fprintf to stderr) + int temp_fd = open(temp_file_.c_str(), OPEN_FLAGS, OPEN_MODE); + if (temp_fd != -1) { + dup2(temp_fd, STDERR_FD); + fd_close(temp_fd); + } + } + + std::string stopCapture() { + // Restore original cerr stream + std::cerr.rdbuf(cerr_backup_); + + // Restore original stderr file descriptor + dup2(stderr_backup_, STDERR_FD); + + // Read from temp file (captures fprintf(stderr) output from HIP logging) + std::ifstream temp_file(temp_file_); + std::string file_content; + if (temp_file.is_open()) { + std::string line; + while (std::getline(temp_file, line)) { + file_content += line + "\n"; + } + temp_file.close(); + } + + // Combine both captures: C++ streams and file descriptor output + std::string stream_content = captured_stream_.str(); + std::string total_output = stream_content + file_content; + + // Clean up temp file + unlink(temp_file_.c_str()); + + return total_output; + } + + ~OutCapture() { + // Ensure everything is restored + std::cerr.rdbuf(cerr_backup_); + dup2(stderr_backup_, STDERR_FD); + fd_close(stderr_backup_); + unlink(temp_file_.c_str()); + } +}; diff --git a/projects/hip-tests/catch/unit/errorHandling/hipDynamicLogging.cc b/projects/hip-tests/catch/unit/errorHandling/hipDynamicLogging.cc new file mode 100644 index 0000000000..d242b12bb1 --- /dev/null +++ b/projects/hip-tests/catch/unit/errorHandling/hipDynamicLogging.cc @@ -0,0 +1,156 @@ +/* +Copyright (c) 2023 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. +*/ + +#include +#include "OutCapture.hh" + +/** + * @addtogroup hipDynamicLogging hipDynamicLogging + * @{ + * @ingroup ErrorTest + * `hipExtSetLoggingParams(size_t log_level, size_t log_size, size_t log_mask)` - + * Sets logging parameters for HIP runtime. + * `hipExtEnableLogging()` - + * Enables HIP runtime logging. + * `hipExtDisableLogging()` - + * Disables HIP runtime logging. + */ + +static bool hipDynamicLoggingTest() { + // Create output capture instance + OutCapture capture; + capture.startCapture(); + + // Set Logging params + HIP_CHECK(hipExtSetLoggingParams(4, 0, -1)); + + // Logging is disabled here - allocate memory + int* dptr = nullptr; + HIP_CHECK(hipMalloc(&dptr, sizeof(int))); + + // Stop capture after hipMalloc and check no output (logging disabled) + std::string malloc_output = capture.stopCapture(); + if (malloc_output.size() != 0) { + INFO("Unexpected logging output during hipMalloc (logging should be disabled): " << malloc_output); + return false; + } + + // Start capture before enabling logging + capture.startCapture(); + + // Enable logging and do memset + HIP_CHECK(hipExtEnableLogging()); + HIP_CHECK(hipMemset(dptr, 0x00, sizeof(int))); + + // Disable logging + HIP_CHECK(hipExtDisableLogging()); + + // Stop capture after disabling logging and check for output + std::string logging_output = capture.stopCapture(); + if (logging_output.size() == 0) { + INFO("Expected logging output during enabled logging period, but got none"); + return false; + } + + // Clean up + HIP_CHECK(hipFree(dptr)); + + INFO("Successfully captured HIP logging output (" << logging_output.size() << " bytes)"); + INFO("Logging output: " << logging_output); + + return true; +} + +/** + * Test Description + * ------------------------ + * - Validates that HIP dynamic logging works correctly: + * 1. No output when logging is disabled + * 2. Logging output is captured when logging is enabled + * 3. hipMemset operation produces logging output during enabled period + * Test source + * ------------------------ + * - unit/errorHandling/hipDynamicLogging.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.6 + */ +TEST_CASE("Unit_hipDynamicLogging_Positive_Basic") { + int numDevices = 0; + HIP_CHECK(hipGetDeviceCount(&numDevices)); + + if (numDevices <= 0) { + HipTest::HIP_SKIP_TEST("Skipping hipDynamicLogging test - no devices available"); + return; + } + + REQUIRE(hipDynamicLoggingTest() == true); +} + +/** + * Test Description + * ------------------------ + * - Validates that hipExtSetLoggingParams sets logging parameters correctly + * and that logging can be enabled/disabled multiple times + * Test source + * ------------------------ + * - unit/errorHandling/hipDynamicLogging.cc + * Test requirements + * ------------------------ + * - HIP_VERSION >= 5.6 + */ +TEST_CASE("Unit_hipDynamicLogging_Positive_MultipleEnableDisable") { + int numDevices = 0; + HIP_CHECK(hipGetDeviceCount(&numDevices)); + + if (numDevices <= 0) { + HipTest::HIP_SKIP_TEST("Skipping hipDynamicLogging test - no devices available"); + return; + } + + // Test multiple enable/disable cycles + OutCapture capture; + int* dptr = nullptr; + HIP_CHECK(hipMalloc(&dptr, sizeof(int))); + + // Set different logging parameters + HIP_CHECK(hipExtSetLoggingParams(3, 0, -1)); + + for (int i = 0; i < 3; ++i) { + // Start capture and enable logging + capture.startCapture(); + HIP_CHECK(hipExtEnableLogging()); + HIP_CHECK(hipMemset(dptr, 0x42, sizeof(int))); + HIP_CHECK(hipExtDisableLogging()); + + // Check that we captured some output + std::string output = capture.stopCapture(); + REQUIRE(output.size() > 0); + } + + HIP_CHECK(hipFree(dptr)); +} + +/** + * End doxygen group ErrorTest. + * @} + */ diff --git a/projects/hip/include/hip/hip_runtime_api.h b/projects/hip/include/hip/hip_runtime_api.h index a7bc73deb1..6f6aee86fe 100644 --- a/projects/hip/include/hip/hip_runtime_api.h +++ b/projects/hip/include/hip/hip_runtime_api.h @@ -9615,6 +9615,45 @@ hipError_t hipDestroySurfaceObject(hipSurfaceObject_t surfaceObject); /** * @} */ + +/** + * @brief Enable HIP runtime logging. + * + * This function enables the HIP runtime logging mechanism, allowing diagnostic + * and trace information to be captured during HIP API execution. + * + * @returns #hipSuccess + * + * @see hipExtDisableLogging, hipExtSetLoggingParams + */ +hipError_t hipExtEnableLogging(); +/** + * @brief Disable HIP runtime logging. + * + * This function disables the HIP runtime logging mechanism, stopping the capture + * of diagnostic and trace information during HIP API execution. + * + * @returns #hipSuccess + * + * @see hipExtEnableLogging, hipExtSetLoggingParams + */ +hipError_t hipExtDisableLogging(); +/** + * @brief Set HIP runtime logging parameters. + * + * This function configures the logging behavior of the HIP runtime, including + * the verbosity level, buffer size, and which components to log. + * + * @param [in] log_level The logging verbosity level. Higher values produce more detailed output. + * @param [in] log_size Reserved for future use. Currently not implemented. + * @param [in] log_mask A bitmask specifying which HIP runtime components to log. + * + * @returns #hipSuccess, #hipErrorInvalidValue + * + * @see hipExtEnableLogging, hipExtDisableLogging + */ +hipError_t hipExtSetLoggingParams(size_t log_level, size_t log_size, size_t log_mask); + #ifdef __cplusplus } /* extern "c" */ #endif diff --git a/projects/rocprofiler-sdk/source/include/rocprofiler-sdk/cxx/enum_string.hpp b/projects/rocprofiler-sdk/source/include/rocprofiler-sdk/cxx/enum_string.hpp index 514d56e632..519f081021 100644 --- a/projects/rocprofiler-sdk/source/include/rocprofiler-sdk/cxx/enum_string.hpp +++ b/projects/rocprofiler-sdk/source/include/rocprofiler-sdk/cxx/enum_string.hpp @@ -1004,6 +1004,11 @@ ROCPROFILER_ENUM_LABEL(ROCPROFILER_HIP_RUNTIME_API_ID_hipGetProcAddress_spt) #if HIP_RUNTIME_API_TABLE_STEP_VERSION >= 20 ROCPROFILER_ENUM_LABEL(ROCPROFILER_HIP_RUNTIME_API_ID_hipKernelGetParamInfo) #endif +#if HIP_RUNTIME_API_TABLE_STEP_VERSION >= 21 +ROCPROFILER_ENUM_LABEL(ROCPROFILER_HIP_RUNTIME_API_ID_hipExtDisableLogging) +ROCPROFILER_ENUM_LABEL(ROCPROFILER_HIP_RUNTIME_API_ID_hipExtEnableLogging) +ROCPROFILER_ENUM_LABEL(ROCPROFILER_HIP_RUNTIME_API_ID_hipExtSetLoggingParams) +#endif #if HIP_RUNTIME_API_TABLE_STEP_VERSION == 0 static_assert(ROCPROFILER_HIP_RUNTIME_API_ID_LAST == 442); #elif HIP_RUNTIME_API_TABLE_STEP_VERSION == 1 @@ -1046,6 +1051,8 @@ static_assert(ROCPROFILER_HIP_RUNTIME_API_ID_LAST == 506); static_assert(ROCPROFILER_HIP_RUNTIME_API_ID_LAST == 507); #elif HIP_RUNTIME_API_TABLE_STEP_VERSION == 20 static_assert(ROCPROFILER_HIP_RUNTIME_API_ID_LAST == 508); +#elif HIP_RUNTIME_API_TABLE_STEP_VERSION == 21 +static_assert(ROCPROFILER_HIP_RUNTIME_API_ID_LAST == 511); #else # if !defined(ROCPROFILER_UNSAFE_NO_VERSION_CHECK) && \ (defined(ROCPROFILER_CI) && ROCPROFILER_CI > 0) diff --git a/projects/rocprofiler-sdk/source/include/rocprofiler-sdk/hip/api_args.h b/projects/rocprofiler-sdk/source/include/rocprofiler-sdk/hip/api_args.h index 17634ce0c8..1e5608b137 100644 --- a/projects/rocprofiler-sdk/source/include/rocprofiler-sdk/hip/api_args.h +++ b/projects/rocprofiler-sdk/source/include/rocprofiler-sdk/hip/api_args.h @@ -3377,6 +3377,26 @@ typedef union rocprofiler_hip_api_args_t size_t* paramSize; } hipKernelGetParamInfo; #endif +#if HIP_RUNTIME_API_TABLE_STEP_VERSION >= 21 + struct + { + // Empty struct has a size of 0 in C but size of 1 in C++. + // Add the rocprofiler_hip_api_no_args struct to fix this + rocprofiler_hip_api_no_args no_args; + } hipExtDisableLogging; + struct + { + // Empty struct has a size of 0 in C but size of 1 in C++. + // Add the rocprofiler_hip_api_no_args struct to fix this + rocprofiler_hip_api_no_args no_args; + } hipExtEnableLogging; + struct + { + size_t log_level; + size_t log_size; + size_t log_mask; + } hipExtSetLoggingParams; +#endif } rocprofiler_hip_api_args_t; ROCPROFILER_EXTERN_C_FINI diff --git a/projects/rocprofiler-sdk/source/include/rocprofiler-sdk/hip/runtime_api_id.h b/projects/rocprofiler-sdk/source/include/rocprofiler-sdk/hip/runtime_api_id.h index 4c2475ddaf..b72d4f2cab 100644 --- a/projects/rocprofiler-sdk/source/include/rocprofiler-sdk/hip/runtime_api_id.h +++ b/projects/rocprofiler-sdk/source/include/rocprofiler-sdk/hip/runtime_api_id.h @@ -575,6 +575,11 @@ typedef enum rocprofiler_hip_runtime_api_id_t // NOLINT(performance-enum-size) #endif #if HIP_RUNTIME_API_TABLE_STEP_VERSION >= 20 ROCPROFILER_HIP_RUNTIME_API_ID_hipKernelGetParamInfo, +#endif +#if HIP_RUNTIME_API_TABLE_STEP_VERSION >= 21 + ROCPROFILER_HIP_RUNTIME_API_ID_hipExtDisableLogging, + ROCPROFILER_HIP_RUNTIME_API_ID_hipExtEnableLogging, + ROCPROFILER_HIP_RUNTIME_API_ID_hipExtSetLoggingParams, #endif ROCPROFILER_HIP_RUNTIME_API_ID_LAST, } rocprofiler_hip_runtime_api_id_t; diff --git a/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/hip/abi.cpp b/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/hip/abi.cpp index 5fa4222ad1..ac149de1d4 100644 --- a/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/hip/abi.cpp +++ b/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/hip/abi.cpp @@ -623,6 +623,12 @@ ROCP_SDK_ENFORCE_ABI(::HipDispatchTable, hipGetProcAddress_spt_fn, 506); ROCP_SDK_ENFORCE_ABI(::HipDispatchTable, hipKernelGetParamInfo_fn, 507); #endif +#if HIP_RUNTIME_API_TABLE_STEP_VERSION >= 21 +ROCP_SDK_ENFORCE_ABI(::HipDispatchTable, hipExtDisableLogging_fn, 508); +ROCP_SDK_ENFORCE_ABI(::HipDispatchTable, hipExtEnableLogging_fn, 509); +ROCP_SDK_ENFORCE_ABI(::HipDispatchTable, hipExtSetLoggingParams_fn, 510); +#endif + #if HIP_RUNTIME_API_TABLE_STEP_VERSION == 0 ROCP_SDK_ENFORCE_ABI_VERSIONING(::HipDispatchTable, 442) #elif HIP_RUNTIME_API_TABLE_STEP_VERSION == 1 @@ -665,6 +671,8 @@ ROCP_SDK_ENFORCE_ABI_VERSIONING(::HipDispatchTable, 506) ROCP_SDK_ENFORCE_ABI_VERSIONING(::HipDispatchTable, 507) #elif HIP_RUNTIME_API_TABLE_STEP_VERSION == 20 ROCP_SDK_ENFORCE_ABI_VERSIONING(::HipDispatchTable, 508) +#elif HIP_RUNTIME_API_TABLE_STEP_VERSION == 21 +ROCP_SDK_ENFORCE_ABI_VERSIONING(::HipDispatchTable, 511) #else INTERNAL_CI_ROCP_SDK_ENFORCE_ABI_VERSIONING(::HipDispatchTable, 0) #endif diff --git a/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/hip/hip.def.cpp b/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/hip/hip.def.cpp index 44cf89d6c1..13e4cd1c76 100644 --- a/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/hip/hip.def.cpp +++ b/projects/rocprofiler-sdk/source/lib/rocprofiler-sdk/hip/hip.def.cpp @@ -650,6 +650,11 @@ HIP_API_INFO_DEFINITION_V(ROCPROFILER_HIP_TABLE_ID_Runtime, ROCPROFILER_HIP_RUNT HIP_API_INFO_DEFINITION_V(ROCPROFILER_HIP_TABLE_ID_Runtime, ROCPROFILER_HIP_RUNTIME_API_ID_hipKernelGetParamInfo, hipKernelGetParamInfo, hipKernelGetParamInfo_fn, kernel, paramIndex, paramOffset, paramSize); #endif +#if HIP_RUNTIME_API_TABLE_STEP_VERSION >= 21 +HIP_API_INFO_DEFINITION_0(ROCPROFILER_HIP_TABLE_ID_Runtime, ROCPROFILER_HIP_RUNTIME_API_ID_hipExtDisableLogging, hipExtDisableLogging, hipExtDisableLogging_fn); +HIP_API_INFO_DEFINITION_0(ROCPROFILER_HIP_TABLE_ID_Runtime, ROCPROFILER_HIP_RUNTIME_API_ID_hipExtEnableLogging, hipExtEnableLogging, hipExtEnableLogging_fn); +HIP_API_INFO_DEFINITION_V(ROCPROFILER_HIP_TABLE_ID_Runtime, ROCPROFILER_HIP_RUNTIME_API_ID_hipExtSetLoggingParams, hipExtSetLoggingParams, hipExtSetLoggingParams_fn, log_level, log_size, log_mask); +#endif // clang-format on #else From 25090e003f5859726d536298ecdb05275068a09d Mon Sep 17 00:00:00 2001 From: jamessiddeley-amd Date: Mon, 19 Jan 2026 19:10:02 -0500 Subject: [PATCH 16/21] [rocprof-compute] Pin ruff version for consistent formatting (#2680) * pin ruff versions each to current latest * Update rocprofiler-compute-formatting.yml * Downgrade .pre-commit-config.yaml to match develop --- .github/workflows/rocprofiler-compute-formatting.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rocprofiler-compute-formatting.yml b/.github/workflows/rocprofiler-compute-formatting.yml index 42f8351d56..0e65719eac 100644 --- a/.github/workflows/rocprofiler-compute-formatting.yml +++ b/.github/workflows/rocprofiler-compute-formatting.yml @@ -41,7 +41,7 @@ jobs: working-directory: projects/rocprofiler-compute run: | python -m pip install --upgrade pip - python -m pip install ruff + python -m pip install ruff==0.14.11 if [ -f requirements.txt ]; then python -m pip install -r requirements.txt; fi - name: Run Ruff Linter and Import Sorter run: | From c83b3aae07b58af2bc7eaca1bd6fb31eea5b9e2c Mon Sep 17 00:00:00 2001 From: David Galiffi Date: Mon, 19 Jan 2026 21:26:50 -0500 Subject: [PATCH 17/21] Fix Python Formatting (#2679) Updated version of black to 26.1.0 updated some formatting rules Signed-off-by: David Galiffi --- .../rocprofiler-systems/source/python/gui/source/gui.py | 1 - .../rocprofiler-systems/source/python/rocprofsys/common.py | 1 - .../rocprofiler-systems/source/python/rocprofsys/user.py | 1 - projects/rocprofiler-systems/tests/validate-causal-json.py | 1 - projects/rocprofiler-systems/tests/validate-rocpd.py | 6 ++---- 5 files changed, 2 insertions(+), 8 deletions(-) diff --git a/projects/rocprofiler-systems/source/python/gui/source/gui.py b/projects/rocprofiler-systems/source/python/gui/source/gui.py index 115e717d5e..6e6233901c 100644 --- a/projects/rocprofiler-systems/source/python/gui/source/gui.py +++ b/projects/rocprofiler-systems/source/python/gui/source/gui.py @@ -47,7 +47,6 @@ from .parser import parse_uploaded_file from .parser import find_causal_files import plotly.graph_objects as go - file_timestamp = 0 global_data = pd.DataFrame() global_samples = pd.DataFrame() diff --git a/projects/rocprofiler-systems/source/python/rocprofsys/common.py b/projects/rocprofiler-systems/source/python/rocprofsys/common.py index 6f4b06e54b..f257e5e8f7 100644 --- a/projects/rocprofiler-systems/source/python/rocprofsys/common.py +++ b/projects/rocprofiler-systems/source/python/rocprofsys/common.py @@ -37,7 +37,6 @@ from . import libpyrocprofsys from .libpyrocprofsys.profiler import profiler_init as _profiler_init from .libpyrocprofsys.profiler import profiler_finalize as _profiler_fini - __all__ = ["exec_", "_file", "_get_argv", "_initialize", "_finalize"] diff --git a/projects/rocprofiler-systems/source/python/rocprofsys/user.py b/projects/rocprofiler-systems/source/python/rocprofsys/user.py index 9e51c9e638..b0871c8071 100644 --- a/projects/rocprofiler-systems/source/python/rocprofsys/user.py +++ b/projects/rocprofiler-systems/source/python/rocprofsys/user.py @@ -44,7 +44,6 @@ from .libpyrocprofsys.user import pop_region from .common import _initialize from .common import _file - __all__ = [ "region", "Region", diff --git a/projects/rocprofiler-systems/tests/validate-causal-json.py b/projects/rocprofiler-systems/tests/validate-causal-json.py index e10578c7f3..c3360d02ac 100755 --- a/projects/rocprofiler-systems/tests/validate-causal-json.py +++ b/projects/rocprofiler-systems/tests/validate-causal-json.py @@ -30,7 +30,6 @@ import math import argparse from collections import OrderedDict - num_stddev = 1.0 diff --git a/projects/rocprofiler-systems/tests/validate-rocpd.py b/projects/rocprofiler-systems/tests/validate-rocpd.py index 43f3241760..4714c282ea 100644 --- a/projects/rocprofiler-systems/tests/validate-rocpd.py +++ b/projects/rocprofiler-systems/tests/validate-rocpd.py @@ -75,8 +75,7 @@ class required_table: def print_help(): """Print out the help message""" - print( - f""" + print(f""" ROCPD Database Validation Tool DESCRIPTION: @@ -115,8 +114,7 @@ def print_help(): 64 - Invalid command line arguments (EX_USAGE) 65 - Validation failures detected (EX_DATAERR) 1 - General error (database connection, file not found, etc.) - """ - ) + """) def validate_table(cursor, rule, tables) -> bool: From b533f56197ba1089653de799f737ab9d0c38626c Mon Sep 17 00:00:00 2001 From: Milan Radosavljevic Date: Tue, 20 Jan 2026 08:42:49 +0100 Subject: [PATCH 18/21] Add automatic PyTorch library discovery for Python applications (#2623) * Add automatic PyTorch library discovery for Python applications (#2623) --- .../source/bin/rocprof-sys-run/impl.cpp | 4 + .../source/bin/rocprof-sys-sample/impl.cpp | 6 + .../rocprof-sys-sample/rocprof-sys-sample.cpp | 2 + .../rocprof-sys-sample/rocprof-sys-sample.hpp | 3 + .../source/lib/common/environment.hpp | 254 +++++++++++++++++- .../source/lib/common/tests/CMakeLists.txt | 1 + .../lib/common/tests/test_environment.cpp | 146 ++++++++++ .../source/lib/core/argparse.cpp | 8 + .../source/lib/core/argparse.hpp | 3 + 9 files changed, 425 insertions(+), 2 deletions(-) create mode 100644 projects/rocprofiler-systems/source/lib/common/tests/test_environment.cpp diff --git a/projects/rocprofiler-systems/source/bin/rocprof-sys-run/impl.cpp b/projects/rocprofiler-systems/source/bin/rocprof-sys-run/impl.cpp index f869ec8ca0..a19121529b 100644 --- a/projects/rocprofiler-systems/source/bin/rocprof-sys-run/impl.cpp +++ b/projects/rocprofiler-systems/source/bin/rocprof-sys-run/impl.cpp @@ -192,6 +192,10 @@ prepare_environment_for_run(parser_data_t& _data) rocprofsys::argparse::add_ld_preload(_data); rocprofsys::argparse::add_ld_library_path(_data); } + + rocprofsys::argparse::add_torch_library_path(_data, _data.verbose > 0); + + rocprofsys::common::consolidate_env_entries(_data.current); } void diff --git a/projects/rocprofiler-systems/source/bin/rocprof-sys-sample/impl.cpp b/projects/rocprofiler-systems/source/bin/rocprof-sys-sample/impl.cpp index 6a4b27edb4..96008b2dc6 100644 --- a/projects/rocprofiler-systems/source/bin/rocprof-sys-sample/impl.cpp +++ b/projects/rocprofiler-systems/source/bin/rocprof-sys-sample/impl.cpp @@ -933,3 +933,9 @@ parse_args(int argc, char** argv, std::vector& _env) return _outv; } + +void +add_torch_library_path(std::vector& envp, const std::vector& argv) +{ + rocprofsys::common::add_torch_library_path(envp, argv, verbose > 0, updated_envs); +} diff --git a/projects/rocprofiler-systems/source/bin/rocprof-sys-sample/rocprof-sys-sample.cpp b/projects/rocprofiler-systems/source/bin/rocprof-sys-sample/rocprof-sys-sample.cpp index 122d02e59d..03098fa03a 100644 --- a/projects/rocprofiler-systems/source/bin/rocprof-sys-sample/rocprof-sys-sample.cpp +++ b/projects/rocprofiler-systems/source/bin/rocprof-sys-sample/rocprof-sys-sample.cpp @@ -51,6 +51,8 @@ main(int argc, char** argv) _argv.emplace_back(argv[i]); } + add_torch_library_path(_env, _argv); + print_updated_environment(_env); if(!_argv.empty()) diff --git a/projects/rocprofiler-systems/source/bin/rocprof-sys-sample/rocprof-sys-sample.hpp b/projects/rocprofiler-systems/source/bin/rocprof-sys-sample/rocprof-sys-sample.hpp index 2134bc0680..8878d92635 100644 --- a/projects/rocprofiler-systems/source/bin/rocprof-sys-sample/rocprof-sys-sample.hpp +++ b/projects/rocprofiler-systems/source/bin/rocprof-sys-sample/rocprof-sys-sample.hpp @@ -35,3 +35,6 @@ get_initial_environment(); std::vector parse_args(int argc, char** argv, std::vector& envp); + +void +add_torch_library_path(std::vector& envp, const std::vector& argv); diff --git a/projects/rocprofiler-systems/source/lib/common/environment.hpp b/projects/rocprofiler-systems/source/lib/common/environment.hpp index 7d2f45eceb..1ff89d355a 100644 --- a/projects/rocprofiler-systems/source/lib/common/environment.hpp +++ b/projects/rocprofiler-systems/source/lib/common/environment.hpp @@ -26,9 +26,12 @@ #include "common/join.hpp" #include +#include #include #include #include +#include +#include #include #include #include @@ -197,7 +200,7 @@ remove_env(std::vector& _environ, std::string_view _env_var, { if(match(itr)) { - free(itr); + std::free(itr); itr = nullptr; } } @@ -266,6 +269,113 @@ discover_llvm_libdir_for_ompt(bool verbose = false) return {}; } +inline bool +is_python_interpreter(std::string_view executable) +{ + if(executable.empty()) return false; + + const auto slash_pos = executable.rfind('/'); + const auto basename = (slash_pos != std::string_view::npos) + ? executable.substr(slash_pos + 1) + : executable; + + if(basename == "python" || basename == "python3") return true; + + constexpr std::string_view python3_prefix = "python3."; + + const bool has_valid_prefix = + basename.size() > python3_prefix.size() && + basename.substr(0, python3_prefix.size()) == python3_prefix; + if(!has_valid_prefix) return false; + + const auto version_digits = basename.substr(python3_prefix.size()); + + return std::all_of(version_digits.begin(), version_digits.end(), + [](unsigned char c) { return std::isdigit(c); }); +} + +inline std::string +discover_torch_libpath(const std::string& python_binary, bool verbose = false) +{ + if(python_binary.empty()) return {}; + + const auto is_safe_executable_path = [](const std::string& path) { + // Allow only a conservative set of characters in the executable path to + // avoid injection when used in a shell command. + for(unsigned char c : path) + { + if(std::isalnum(c) != 0) continue; + switch(c) + { + case '/': + case '.': + case '_': + case '-': + case '+': break; + default: return false; + } + } + return true; + }; + + if(!is_safe_executable_path(python_binary)) + { + ROCPROFSYS_ENVIRON_LOG( + verbose, "Unsafe characters detected in Python interpreter path: %s\n", + python_binary.c_str()); + return {}; + } + + const auto cmd = "\"" + python_binary + + "\" -c \"import torch; print(torch.__path__[0])\" 2>/dev/null"; + + FILE* pipe = popen(cmd.c_str(), "r"); + if(!pipe) + { + ROCPROFSYS_ENVIRON_LOG(verbose, "Failed to execute command: %s\n", cmd.c_str()); + return {}; + } + + char buffer[1024]; + std::string result; + while(fgets(buffer, sizeof(buffer), pipe)) + { + result.append(buffer); + // stop if we've read the full line (torch path is printed on a single line) + if(!result.empty() && result.back() == '\n') break; + } + + int status = pclose(pipe); + + if(status != 0 || result.empty()) + { + ROCPROFSYS_ENVIRON_LOG(verbose, "torch not found for Python interpreter: %s\n", + python_binary.c_str()); + return {}; + } + + while(!result.empty() && + (result.back() == '\n' || result.back() == '\r' || result.back() == ' ')) + { + result.pop_back(); + } + + if(result.empty()) return {}; + + std::string torch_libdir = result + "/lib"; + + if(!::tim::filepath::direxists(torch_libdir)) + { + ROCPROFSYS_ENVIRON_LOG(verbose, "torch lib directory does not exist: %s\n", + torch_libdir.c_str()); + return {}; + } + + ROCPROFSYS_ENVIRON_LOG(verbose, "Discovered torch library path: %s\n", + torch_libdir.c_str()); + return torch_libdir; +} + enum class update_mode : uint8_t { REPLACE = 0, @@ -335,7 +445,7 @@ update_env(std::vector& _environ, std::string_view _env_var, Tp&& _env_va } else { - free(itr); + std::free(itr); itr = strdup(join('=', _env_var, _env_val_str).c_str()); } return; @@ -343,5 +453,145 @@ update_env(std::vector& _environ, std::string_view _env_var, Tp&& _env_va _environ.emplace_back(strdup(join('=', _env_var, _env_val_str).c_str())); } +template +inline void +add_torch_library_path(std::vector& envp, const std::vector& argv, + bool verbose, UpdatedEnvsT& updated_envs) +{ + if(argv.empty() || argv.front() == nullptr) return; + if(!is_python_interpreter(argv.front())) return; + + auto torch_libpath = discover_torch_libpath(argv.front(), verbose); + if(torch_libpath.empty()) return; + + std::unordered_set seen{ torch_libpath }; + std::string result = torch_libpath; + + constexpr std::string_view ld_prefix = "LD_LIBRARY_PATH="; + + auto is_ld_path = [&](char* entry) { + return entry && + std::string_view{ entry }.substr(0, ld_prefix.length()) == ld_prefix; + }; + + for(auto& entry : envp) + { + if(!is_ld_path(entry)) continue; + + std::istringstream stream{ std::string{ entry + ld_prefix.length() } }; + for(std::string path; std::getline(stream, path, ':');) + { + if(!path.empty() && seen.insert(path).second) result += ":" + path; + } + + std::free(entry); + entry = nullptr; + } + + envp.erase(std::remove(envp.begin(), envp.end(), nullptr), envp.end()); + envp.emplace_back(strdup(join("", ld_prefix, result).c_str())); + + updated_envs.emplace(ld_prefix.substr(0, ld_prefix.length() - 1)); +} + +inline void +consolidate_env_entries(std::vector& envp) +{ + constexpr char delim = ':'; + + struct key_data + { + std::vector parts; + std::unordered_set seen; + + void add_unique(std::string part) + { + if(!part.empty() && seen.insert(part).second) + parts.emplace_back(std::move(part)); + } + }; + + auto parse_entry = [](std::string_view entry) + -> std::optional> { + auto eq_pos = entry.find('='); + if(eq_pos == std::string_view::npos) return std::nullopt; + return std::make_pair(entry.substr(0, eq_pos), entry.substr(eq_pos + 1)); + }; + + auto join_parts = [delim](std::string_view key, + const std::vector& parts) { + std::string result; + + const auto total_parts_length = std::accumulate( + parts.begin(), parts.end(), std::size_t{ 0 }, + [](std::size_t acc, const std::string& part) { return acc + part.size(); }); + + const auto delim_count = parts.size() - 1; + const auto equal_sign_length = 1; + + result.reserve(key.size() + equal_sign_length + total_parts_length + delim_count); + result.append(key); + result += '='; + + result = + std::accumulate(parts.begin(), parts.end(), std::move(result), + [delim, &parts](std::string acc, const std::string& part) { + if(part != parts.front()) acc += delim; + acc.append(part); + return acc; + }); + + return result; + }; + + std::unordered_map key_map; + std::vector key_order; + + for(auto* entry : envp) + { + if(!entry) + { + continue; + } + + auto parsed = parse_entry(entry); + if(!parsed) + { + continue; + } + + auto [key, value] = *parsed; + + auto [it, inserted] = key_map.try_emplace(key); + if(inserted) + { + key_order.emplace_back(key); + } + + auto& data = it->second; + std::istringstream stream{ std::string{ value } }; + for(std::string part; std::getline(stream, part, delim);) + { + data.add_unique(part); + } + } + + std::vector result; + result.reserve(key_order.size()); + + for(auto key : key_order) + { + result.emplace_back(strdup(join_parts(key, key_map[key].parts).c_str())); + } + + for(auto* entry : envp) + { + std::free(entry); + entry = nullptr; + } + + envp = std::move(result); +} + } // namespace common } // namespace rocprofsys diff --git a/projects/rocprofiler-systems/source/lib/common/tests/CMakeLists.txt b/projects/rocprofiler-systems/source/lib/common/tests/CMakeLists.txt index 79d3f4ad03..4e2391824c 100644 --- a/projects/rocprofiler-systems/source/lib/common/tests/CMakeLists.txt +++ b/projects/rocprofiler-systems/source/lib/common/tests/CMakeLists.txt @@ -24,6 +24,7 @@ add_library( lib-common-tests OBJECT test_discover_llvm_libdir.cpp + test_environment.cpp test_path.cpp test_remove_env.cpp test_update_env.cpp diff --git a/projects/rocprofiler-systems/source/lib/common/tests/test_environment.cpp b/projects/rocprofiler-systems/source/lib/common/tests/test_environment.cpp new file mode 100644 index 0000000000..7c33603aa1 --- /dev/null +++ b/projects/rocprofiler-systems/source/lib/common/tests/test_environment.cpp @@ -0,0 +1,146 @@ +// Copyright (c) Advanced Micro Devices, Inc. +// SPDX-License-Identifier: MIT + +#include "common/environment.hpp" + +#include + +using namespace rocprofsys::common; + +class IsPythonInterpreterTest : public ::testing::Test +{}; + +TEST_F(IsPythonInterpreterTest, RecognizesPython) +{ + EXPECT_TRUE(is_python_interpreter("python")); + EXPECT_TRUE(is_python_interpreter("python3")); + EXPECT_TRUE(is_python_interpreter("python3.8")); + EXPECT_TRUE(is_python_interpreter("python3.9")); + EXPECT_TRUE(is_python_interpreter("python3.10")); + EXPECT_TRUE(is_python_interpreter("python3.11")); + EXPECT_TRUE(is_python_interpreter("python3.12")); + EXPECT_TRUE(is_python_interpreter("/usr/bin/python")); + EXPECT_TRUE(is_python_interpreter("/usr/bin/python3")); + EXPECT_TRUE(is_python_interpreter("/usr/bin/python3.10")); + EXPECT_TRUE(is_python_interpreter("/home/user/venv/bin/python")); + EXPECT_TRUE(is_python_interpreter("/opt/conda/bin/python3.11")); + EXPECT_FALSE(is_python_interpreter("bash")); + EXPECT_FALSE(is_python_interpreter("sh")); + EXPECT_FALSE(is_python_interpreter("ruby")); + EXPECT_FALSE(is_python_interpreter("node")); + EXPECT_FALSE(is_python_interpreter("java")); + EXPECT_FALSE(is_python_interpreter("/usr/bin/bash")); + EXPECT_FALSE(is_python_interpreter("./my_app")); + EXPECT_FALSE(is_python_interpreter("pythonista")); + EXPECT_FALSE(is_python_interpreter("python_script.py")); + EXPECT_FALSE(is_python_interpreter("mypython")); + EXPECT_FALSE(is_python_interpreter("python2")); + EXPECT_FALSE(is_python_interpreter("python3.")); + EXPECT_FALSE(is_python_interpreter("python3.a")); + EXPECT_FALSE(is_python_interpreter("python3.10a")); + EXPECT_FALSE(is_python_interpreter("python3x10")); + EXPECT_FALSE(is_python_interpreter("")); + EXPECT_FALSE(is_python_interpreter("/usr/bin/")); +} + +class DuplicatedEnvironmentEntriesTest : public ::testing::Test +{}; + +TEST_F(DuplicatedEnvironmentEntriesTest, DuplicateEnvironmentEntries) +{ + std::vector env_vars = { + strdup("PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/bin2"), + strdup("PATH=/usr/local/bin:/usr/bin:/bin"), + }; + + consolidate_env_entries(env_vars); + + ASSERT_EQ(env_vars.size(), 1); + EXPECT_STREQ(env_vars[0], "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/bin2"); + + for(auto* entry : env_vars) + free(entry); +} + +TEST_F(DuplicatedEnvironmentEntriesTest, HandlesEmptyVector) +{ + std::vector env_vars; + consolidate_env_entries(env_vars); + EXPECT_TRUE(env_vars.empty()); +} + +TEST_F(DuplicatedEnvironmentEntriesTest, HandlesNullEntries) +{ + std::vector env_vars = { + strdup("PATH=/usr/bin"), + nullptr, + strdup("PATH=/bin"), + }; + consolidate_env_entries(env_vars); + ASSERT_EQ(env_vars.size(), 1); + EXPECT_STREQ(env_vars[0], "PATH=/usr/bin:/bin"); + for(auto* entry : env_vars) + std::free(entry); +} + +TEST_F(DuplicatedEnvironmentEntriesTest, HandlesEmptyValues) +{ + std::vector env_vars = { + strdup("EMPTY_VAR="), + strdup("PATH=/usr/bin"), + }; + consolidate_env_entries(env_vars); + ASSERT_EQ(env_vars.size(), 2); + + for(auto* entry : env_vars) + std::free(entry); +} + +class AddTorchLibraryPathTest : public ::testing::Test +{ +protected: + std::unordered_set updated_envs; +}; + +TEST_F(AddTorchLibraryPathTest, SkipsNonPythonExecutables) +{ + std::vector envp = { + strdup("LD_LIBRARY_PATH=/usr/lib"), + }; + std::vector argv = { + strdup("/usr/bin/bash"), + }; + add_torch_library_path(envp, argv, false, updated_envs); + // Should not modify environment + ASSERT_EQ(envp.size(), 1); + EXPECT_STREQ(envp[0], "LD_LIBRARY_PATH=/usr/lib"); + for(auto* entry : envp) + std::free(entry); + for(auto* entry : argv) + std::free(entry); +} + +TEST_F(AddTorchLibraryPathTest, HandlesEmptyArgv) +{ + std::vector envp = { + strdup("LD_LIBRARY_PATH=/usr/lib"), + }; + std::vector argv; + add_torch_library_path(envp, argv, false, updated_envs); + ASSERT_EQ(envp.size(), 1); + EXPECT_STREQ(envp[0], "LD_LIBRARY_PATH=/usr/lib"); + for(auto* entry : envp) + std::free(entry); +} + +TEST_F(AddTorchLibraryPathTest, HandlesNullArgvFront) +{ + std::vector envp = { + strdup("LD_LIBRARY_PATH=/usr/lib"), + }; + std::vector argv = { nullptr }; + add_torch_library_path(envp, argv, false, updated_envs); + ASSERT_EQ(envp.size(), 1); + for(auto* entry : envp) + std::free(entry); +} diff --git a/projects/rocprofiler-systems/source/lib/core/argparse.cpp b/projects/rocprofiler-systems/source/lib/core/argparse.cpp index c4230ff807..b4ea4c41d1 100644 --- a/projects/rocprofiler-systems/source/lib/core/argparse.cpp +++ b/projects/rocprofiler-systems/source/lib/core/argparse.cpp @@ -168,6 +168,14 @@ add_ld_library_path(parser_data& _data) return _data; } +parser_data& +add_torch_library_path(parser_data& _data, bool verbose) +{ + rocprofsys::common::add_torch_library_path(_data.current, _data.command, verbose, + _data.updated); + return _data; +} + parser_data& add_core_arguments(parser_t& _parser, parser_data& _data) { diff --git a/projects/rocprofiler-systems/source/lib/core/argparse.hpp b/projects/rocprofiler-systems/source/lib/core/argparse.hpp index 9280ddd4f9..744c097b0e 100644 --- a/projects/rocprofiler-systems/source/lib/core/argparse.hpp +++ b/projects/rocprofiler-systems/source/lib/core/argparse.hpp @@ -83,6 +83,9 @@ add_ld_preload(parser_data&); parser_data& add_ld_library_path(parser_data&); +parser_data& +add_torch_library_path(parser_data&, bool verbose = false); + parser_data& add_core_arguments(parser_t&, parser_data&); From 51f49d8835506d66d60aaa22c9d7bd3275a51c01 Mon Sep 17 00:00:00 2001 From: marantic-amd Date: Tue, 20 Jan 2026 13:59:31 +0100 Subject: [PATCH 19/21] Add notice for the newly deprecated env variables (#2690) --- projects/rocprofiler-systems/source/lib/core/config.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/projects/rocprofiler-systems/source/lib/core/config.cpp b/projects/rocprofiler-systems/source/lib/core/config.cpp index 192875063e..b4a1cbe6e0 100644 --- a/projects/rocprofiler-systems/source/lib/core/config.cpp +++ b/projects/rocprofiler-systems/source/lib/core/config.cpp @@ -316,7 +316,9 @@ configure_settings(bool _init) "backend", "perfetto"); ROCPROFSYS_CONFIG_SETTING(bool, "ROCPROFSYS_TRACE_LEGACY", - "Use legacy direct mode for perfetto tracing instead of " + "[DEPRECATED] The new default option is to use data from " + "cached buffer. When set to true system will use " + "legacy direct mode for perfetto tracing instead of " "deferred trace generation. When false (default), uses " "cached mode with minimal runtime overhead.", false, "backend", "perfetto"); @@ -1088,6 +1090,9 @@ configure_settings(bool _init) handle_deprecated_setting("ROCPROFSYS_OUTPUT_FILE", "ROCPROFSYS_PERFETTO_FILE"); handle_deprecated_setting("ROCPROFSYS_USE_PERFETTO", "ROCPROFSYS_TRACE"); handle_deprecated_setting("ROCPROFSYS_USE_TIMEMORY", "ROCPROFSYS_PROFILE"); + handle_deprecated_setting("ROCPROFSYS_DEBUG", "ROCPROFSYS_LOG_LEVEL"); + handle_deprecated_setting("ROCPROFSYS_VERBOSE", "ROCPROFSYS_LOG_LEVEL"); + handle_deprecated_setting("ROCPROFSYS_TRACE_LEGACY", "ROCPROFSYS_TRACE"); scope::get_fields()[scope::flat::value] = _config->get_flat_profile(); scope::get_fields()[scope::timeline::value] = _config->get_timeline_profile(); From a926660670806fc8ec1444a13b6f66b803135e19 Mon Sep 17 00:00:00 2001 From: vedithal-amd Date: Tue, 20 Jan 2026 09:54:38 -0500 Subject: [PATCH 20/21] [rocprofiler-compute] Use TheRock nightly builds in testing container (#2661) * Use TheRock nightly builds in testing container * Add HIP_DEVICE_LIB_PATH env var for hipcc to work * Add HIP_PLATFORM env var for cmake hip package * Add tarball placeholder * Add -f to curl command to fail on HTTP error --- projects/rocprofiler-compute/README.md | 4 +- .../docker/Dockerfile.customrocmtest | 44 ++++++++++++++----- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/projects/rocprofiler-compute/README.md b/projects/rocprofiler-compute/README.md index b7ed73b217..f913e5ad47 100644 --- a/projects/rocprofiler-compute/README.md +++ b/projects/rocprofiler-compute/README.md @@ -38,8 +38,8 @@ python3 -m pip install -r requirements.txt ## Testing -Populate the variable in `docker/docker-compose.customrocmtest.yml`. -Populate the variable in `docker/Dockerfile.customrocmtest` based on latest ROCm CI build information. +Populate the variable in `docker/docker-compose.customrocmtest.yml`. +Populate the variable in `docker/Dockerfile.customrocmtest` based on latest TheRock nightly build information. To quickly get the environment (bash shell) for building and testing, run the following commands: * `cd docker` diff --git a/projects/rocprofiler-compute/docker/Dockerfile.customrocmtest b/projects/rocprofiler-compute/docker/Dockerfile.customrocmtest index 47ec351559..020f8b0e4c 100644 --- a/projects/rocprofiler-compute/docker/Dockerfile.customrocmtest +++ b/projects/rocprofiler-compute/docker/Dockerfile.customrocmtest @@ -1,32 +1,52 @@ # Use a base image -FROM +FROM ubuntu:22.04 -# Set the working directory -WORKDIR /app +# Install curl first (needed for ROCm download) +RUN apt-get update && apt-get install -y curl + +# Define the tarball name as a variable +# Check https://therock-nightly-tarball.s3.amazonaws.com/index.html for latest builds +# Use therock-dist-linux-gfx-dcgpu-.tar.gz naming convention +ARG TARBALL_NAME= + +# Install ROCm from TheRock Nightly build +RUN mkdir -p /rocm && \ + curl -fLO https://therock-nightly-tarball.s3.amazonaws.com/${TARBALL_NAME} && \ + tar -xf ${TARBALL_NAME} -C /rocm && \ + rm ${TARBALL_NAME} + +# Set environment variables for ROCm +ENV PATH="/rocm/bin:${PATH}" \ + ROCM_PATH="/rocm" \ + LD_LIBRARY_PATH="/rocm/lib:/rocm/lib/rocm_sysdeps/lib:${LD_LIBRARY_PATH}" \ + HIP_DEVICE_LIB_PATH="/rocm/llvm/amdgcn/bitcode" \ + HIP_PLATFORM=amd # Update package list and install prerequisites RUN apt-get update && apt-get install -y \ - software-properties-common cmake locales git curl \ + software-properties-common cmake locales git \ && add-apt-repository ppa:deadsnakes/ppa \ && apt-get update -# Allows running git commands in /app -RUN git config --global --add safe.directory /app - # Generate the desired locale RUN locale-gen en_US.UTF-8 # Install Python 3.10 and pip RUN apt-get install -y python3.10 python3.10-venv python3.10-dev python3-pip libsqlite3-dev -RUN python3.10 -m venv venv -ENV PATH="venv/bin:$PATH" +RUN python3.10 -m venv /venv +ENV PATH="/venv/bin:$PATH" RUN python -m pip install --upgrade pip -# Install any dependencies specified in requirements.txt -WORKDIR /app/projects/rocprofiler-compute +# Install any rocprofiler-compute dependencies specified in requirements.txt COPY projects/rocprofiler-compute/requirements.txt /app/projects/rocprofiler-compute/requirements.txt COPY projects/rocprofiler-compute/requirements-test.txt /app/projects/rocprofiler-compute/requirements-test.txt -RUN python -m pip install -r requirements.txt -r requirements-test.txt +RUN python -m pip install -r /app/projects/rocprofiler-compute/requirements.txt -r /app/projects/rocprofiler-compute/requirements-test.txt + +# Set the working directory +WORKDIR /app + +# Allows running git commands in /app +RUN git config --global --add safe.directory /app # Run interactive bash shell CMD ["/bin/bash"] From 4a5cbbfba5fd8fa13995fb2ad5ed9518b51da265 Mon Sep 17 00:00:00 2001 From: vedithal-amd Date: Tue, 20 Jan 2026 10:02:31 -0500 Subject: [PATCH 21/21] [rocprofiler-compute] Fix kernel/dispatch filtering (#2479) * Fix kernel/dispatch fitlering in GUI * Disallow --kernel and --dispatch filtering in analyze --gui mode since GUI frontend offers dropdown menu for kernel and dispatch filtering * Update CHANGELOG and documentation * Gracefully handle N/A values * Ensure workload path is valid before using it in GUI * Ignore kernel filters if dispatch filters provided * Add documentation for dispatch filtering overriding kernel filtering * Fix typo * Fix documentation * remove unnecessary whitespace * Address review comments * Allow kernel/dispatch filtering with --gui * Address review comments * Address review comments * Update CHANGELOG * Fix formatting --- projects/rocprofiler-compute/CHANGELOG.md | 2 ++ .../docs/how-to/analyze/cli.rst | 7 +--- .../docs/how-to/analyze/standalone-gui.rst | 4 ++- .../rocprof_compute_analyze/analysis_base.py | 34 +++++++++---------- .../rocprof_compute_analyze/analysis_webui.py | 3 +- projects/rocprofiler-compute/src/utils/gui.py | 10 +++--- .../rocprofiler-compute/src/utils/parser.py | 4 ++- 7 files changed, 33 insertions(+), 31 deletions(-) diff --git a/projects/rocprofiler-compute/CHANGELOG.md b/projects/rocprofiler-compute/CHANGELOG.md index d541344ae7..ed1625615c 100644 --- a/projects/rocprofiler-compute/CHANGELOG.md +++ b/projects/rocprofiler-compute/CHANGELOG.md @@ -49,6 +49,8 @@ Full documentation for ROCm Compute Profiler is available at [https://rocm.docs. * Fix issue where counter collection data was empty when profiling workload which spawn multiple child processes +* Fix issue where dispatch filtering in a range (e.g. >2) was not working + * Fix redundant warnings for compute/memory partition not found for < MI 300 series GPUs by skipping partition checks ### Removed diff --git a/projects/rocprofiler-compute/docs/how-to/analyze/cli.rst b/projects/rocprofiler-compute/docs/how-to/analyze/cli.rst index 26238c154c..7385f21834 100644 --- a/projects/rocprofiler-compute/docs/how-to/analyze/cli.rst +++ b/projects/rocprofiler-compute/docs/how-to/analyze/cli.rst @@ -346,6 +346,7 @@ Show System Speed-of-Light and CS_Busy blocks only this case, ``1`` is the ID for System Speed-of-Light and ``5.1.0`` the ID for GPU Busy Cycles metric. + Filter kernels First, list the top kernels in your application using `--list-stats`. @@ -562,12 +563,6 @@ WARNING Failed to evaluate expression for 3.1.39 - Value: to_round((to_avg( (pmc_df.get("pmc_perf_ACCUM") / pmc_df.get("SQC_ICACHE_REQ")).where((pmc_df.get("SQC_ICACHE_REQ") != 0), None)) * 100), 0) - unsupported operand type(s) for /: 'NoneType' and 'float' WARNING Failed to evaluate expression for 3.1.39 - Value: to_round((to_avg( (pmc_df.get("pmc_perf_ACCUM") / pmc_df.get("SQC_ICACHE_REQ")).where((pmc_df.get("SQC_ICACHE_REQ") != 0), None)) * 100), 0) - unsupported operand type(s) for /: 'NoneType' and 'float' - DEBUG Calculating expressions for kernel: _ZN12rocrand_impl6system6detail17trampoline_kernelINS_4host33static_block_size_config_providerILj256EEEjLb0ELNS3_11target_archE942EZNS3_25xorwow_generator_templateINS0_13device_systemENS3_23default_config_providerIL16rocrand_rng_type401EEEE4initEvEUlT_DpT0_E_JPN14rocrand_device13xorwow_engineEjjyyEEEvT3_DpT4_ - DEBUG Calculating expressions for kernel: _ZN12rocrand_impl6system6detail17trampoline_kernelINS_4host23default_config_providerIL16rocrand_rng_type401EEEfLb0ELNS3_11target_archE942EZZNS3_25xorwow_generator_templateINS0_13device_systemES6_E8generateIfNS3_20uniform_distributionIfjEEEE14rocrand_statusPT_mT0_ENKUlSF_E_clISt17integral_constantIbLb0EEEEDaSF_EUlSF_DpT0_E_JPN14rocrand_device13xorwow_engineEjPfmSD_EEEvT3_DpT4_ - DEBUG Calculating expressions for kernel: void bodyForce_block<256>(HIP_vector_type const*, HIP_vector_type*, float, int) - DEBUG Calculating expressions for kernel: _ZN12rocrand_impl6system6detail17trampoline_kernelINS_4host33static_block_size_config_providerILj256EEEjLb0ELNS3_11target_archE942EZNS3_25xorwow_generator_templateINS0_13device_systemENS3_23default_config_providerIL16rocrand_rng_type401EEEE4initEvEUlT_DpT0_E_JPN14rocrand_device13xorwow_engineEjjyyEEEvT3_DpT4_ - DEBUG Calculating expressions for kernel: _ZN12rocrand_impl6system6detail17trampoline_kernelINS_4host23default_config_providerIL16rocrand_rng_type401EEEfLb0ELNS3_11target_archE942EZZNS3_25xorwow_generator_templateINS0_13device_systemES6_E8generateIfNS3_20uniform_distributionIfjEEEE14rocrand_statusPT_mT0_ENKUlSF_E_clISt17integral_constantIbLb0EEEEDaSF_EUlSF_DpT0_E_JPN14rocrand_device13xorwow_engineEjPfmSD_EEEvT3_DpT4_ - DEBUG Calculating expressions for kernel: void bodyForce_block<256>(HIP_vector_type const*, HIP_vector_type*, float, int) DEBUG Calculated metric values DEBUG Calculated roofline data points DEBUG [analysis] generating analysis diff --git a/projects/rocprofiler-compute/docs/how-to/analyze/standalone-gui.rst b/projects/rocprofiler-compute/docs/how-to/analyze/standalone-gui.rst index e7cedb3fa1..41b2176411 100644 --- a/projects/rocprofiler-compute/docs/how-to/analyze/standalone-gui.rst +++ b/projects/rocprofiler-compute/docs/how-to/analyze/standalone-gui.rst @@ -28,7 +28,9 @@ Launch the standalone GUI analyzer ---------------------------------- To launch the ROCm Compute Profiler GUI analyzer, include the ``--gui`` flag with your -desired analysis command. For example: +desired analysis command. + +For example: .. code-block:: shell-session diff --git a/projects/rocprofiler-compute/src/rocprof_compute_analyze/analysis_base.py b/projects/rocprofiler-compute/src/rocprof_compute_analyze/analysis_base.py index 7cfe42403d..b4edad07fd 100644 --- a/projects/rocprofiler-compute/src/rocprof_compute_analyze/analysis_base.py +++ b/projects/rocprofiler-compute/src/rocprof_compute_analyze/analysis_base.py @@ -386,26 +386,24 @@ class OmniAnalyze_Base: sys.exit(0) # Ensure analysis output does not overwrite existing files - if not args.output_name: - return + if args.output_name: + if not re.match(r"^[A-Za-z0-9_-]+$", args.output_name): + console_error( + "analysis", + "Analysis output file/folder name must " + "contain only alphanumeric characters " + "or underscores (_), hyphens (-).", + ) - if not re.match(r"^[A-Za-z0-9_-]+$", args.output_name): - console_error( - "analysis", - "Analysis output file/folder name must " - "contain only alphanumeric characters " - "or underscores (_), hyphens (-).", - ) + path_to_check = args.output_name + if args.output_format in ("txt", "db"): + path_to_check += f".{args.output_format}" - path_to_check = args.output_name - if args.output_format in ("txt", "db"): - path_to_check += f".{args.output_format}" - - if Path(path_to_check).exists(): - console_error( - f"Analysis output file/folder {path_to_check} already exists. " - "Please choose a different name." - ) + if Path(path_to_check).exists(): + console_error( + f"Analysis output file/folder {path_to_check} already exists. " + "Please choose a different name." + ) # Check if any kernel's counters are missing due to iteration multiplexing if ( diff --git a/projects/rocprofiler-compute/src/rocprof_compute_analyze/analysis_webui.py b/projects/rocprofiler-compute/src/rocprof_compute_analyze/analysis_webui.py index 40df31abc4..745b7febd0 100644 --- a/projects/rocprofiler-compute/src/rocprof_compute_analyze/analysis_webui.py +++ b/projects/rocprofiler-compute/src/rocprof_compute_analyze/analysis_webui.py @@ -51,7 +51,6 @@ class webui_analysis(OmniAnalyze_Base): self.app = dash.Dash( __name__, title=PROJECT_NAME, external_stylesheets=[dbc.themes.CYBORG] ) - self.dest_dir = str(Path(args.path[0][0]).absolute().resolve()) self.arch: Optional[str] = None self.__hidden_sections = ["Memory Chart"] @@ -90,6 +89,7 @@ class webui_analysis(OmniAnalyze_Base): kernel_top_df = base_data.dfs[1] for kernel_id in base_data.filter_kernel_ids: filt_kernel_names.append(str(kernel_top_df.loc[kernel_id, "Kernel_Name"])) + input_filters["kernel"] = filt_kernel_names # setup app layout from utils.gui_components.header import get_header @@ -338,6 +338,7 @@ class webui_analysis(OmniAnalyze_Base): ) args = self.get_args() + self.dest_dir = str(Path(args.path[0][0]).absolute().resolve()) # create 'mega dataframe' self._runs[self.dest_dir].raw_pmc = file_io.create_df_pmc( diff --git a/projects/rocprofiler-compute/src/utils/gui.py b/projects/rocprofiler-compute/src/utils/gui.py index a03ab297b4..2708365515 100644 --- a/projects/rocprofiler-compute/src/utils/gui.py +++ b/projects/rocprofiler-compute/src/utils/gui.py @@ -61,7 +61,7 @@ def multi_bar_chart( def create_instruction_mix_bar_chart(display_df: pd.DataFrame, df_unit: str) -> px.bar: display_df = display_df.copy() - display_df["Avg"] = display_df["Avg"].apply(lambda x: int(x) if x != "" else 0) + display_df["Avg"] = display_df["Avg"].apply(lambda x: int(x) if x != "N/A" else 0) return px.bar( display_df, @@ -78,7 +78,7 @@ def create_multi_bar_charts( display_df: pd.DataFrame, table_id: int, df_unit: str ) -> list[px.bar]: display_df = display_df.copy() - display_df["Avg"] = display_df["Avg"].apply(lambda x: int(x) if x != "" else 0) + display_df["Avg"] = display_df["Avg"].apply(lambda x: int(x) if x != "N/A" else 0) nested_bar = multi_bar_chart(table_id, display_df) charts = [] @@ -103,7 +103,9 @@ def create_multi_bar_charts( def create_sol_charts(display_df: pd.DataFrame, table_id: int) -> list[px.bar]: display_df = display_df.copy() - display_df["Avg"] = display_df["Avg"].apply(lambda x: float(x) if x != "" else 0.0) + display_df["Avg"] = display_df["Avg"].apply( + lambda x: float(x) if x != "N/A" else 0.0 + ) charts = [] @@ -144,7 +146,7 @@ def create_sol_charts(display_df: pd.DataFrame, table_id: int) -> list[px.bar]: elif table_id == 1101: # Special formatting reference 'Pct of Peak' value display_df["Pct of Peak"] = display_df["Pct of Peak"].apply( - lambda x: float(x) if x != "" else 0.0 + lambda x: float(x) if x != "N/A" else 0.0 ) charts.append( px.bar( diff --git a/projects/rocprofiler-compute/src/utils/parser.py b/projects/rocprofiler-compute/src/utils/parser.py index 4ae6c9759a..68b56396c5 100755 --- a/projects/rocprofiler-compute/src/utils/parser.py +++ b/projects/rocprofiler-compute/src/utils/parser.py @@ -1290,6 +1290,8 @@ def apply_dispatch_filter(df: pd.DataFrame, workload: schema.Workload) -> pd.Dat # NB: support ignoring the 1st n dispatched execution by '> n' # The better way may be parsing python slice string for dispatch_id in workload.filter_dispatch_ids: + if isinstance(dispatch_id, str) and ">" in dispatch_id: + dispatch_id = re.match(r"\>\s*(\d+)", dispatch_id).group(1) if int(dispatch_id) >= len(df): # subtract 2 bc of the two header rows console_error("analysis", f"{dispatch_id} is an invalid dispatch id.") @@ -1297,7 +1299,7 @@ def apply_dispatch_filter(df: pd.DataFrame, workload: schema.Workload) -> pd.Dat isinstance(workload.filter_dispatch_ids[0], str) and ">" in workload.filter_dispatch_ids[0] ): - dispatch_match = re.match(r"\> (\d+)", workload.filter_dispatch_ids[0]) + dispatch_match = re.match(r"\>\s*(\d+)", workload.filter_dispatch_ids[0]) df = df[ df[schema.PMC_PERF_FILE_PREFIX]["Dispatch_ID"] > int(dispatch_match.group(1))