[roctx] Python bindings for rocprofiler-sdk-roctx (#402)

* [roctx] Python bindings for rocprofiler-sdk-roctx

* Update CHANGELOG

---------

Co-authored-by: Jonathan R. Madsen <jonathanrmadsen@gmail.com>
Этот коммит содержится в:
Madsen, Jonathan
2025-05-19 20:02:51 -05:00
коммит произвёл GitHub
родитель afb27f3f1a
Коммит 14c2dc55ff
16 изменённых файлов: 888 добавлений и 1 удалений
+16
Просмотреть файл
@@ -0,0 +1,16 @@
#
# Python package
#
set(DEFAULT_PYTHON_RPATH "\$ORIGIN:\$ORIGIN/../../..:\$ORIGIN/../../../rocprofiler-sdk")
include("${CMAKE_CURRENT_LIST_DIR}/utilities.cmake")
if(NOT DEFINED ROCPROFILER_PYTHON_VERSIONS)
get_default_python_version(DEFAULT_PYTHON_VERSION)
set(ROCPROFILER_PYTHON_VERSIONS
"${DEFAULT_PYTHON_VERSION}"
CACHE STRING "")
endif()
add_subdirectory(roctx)
+9
Просмотреть файл
@@ -0,0 +1,9 @@
#
#
#
foreach(_PYTHON_VERSION ${ROCPROFILER_PYTHON_VERSIONS})
rocprofiler_roctx_python_bindings(${_PYTHON_VERSION})
endforeach()
rocprofiler_reset_python3_cache()
+89
Просмотреть файл
@@ -0,0 +1,89 @@
###############################################################################
# MIT License
#
# Copyright (c) 2023 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.
###############################################################################
from . import libpyroctx
from . import context_decorators
__all__ = [
"mark",
"profilerPause",
"profilerResume",
"getThreadId",
"rangePush",
"rangePop",
"rangeStart",
"rangeStop",
"nameOsThread",
"nameHipDevice",
"context_decorators",
]
def mark(msg):
return libpyroctx.roctxMark(msg) if msg is not None else None
def profilerPause(tid=0):
return libpyroctx.roctxProfilerPause(tid)
def profilerResume(tid=0):
return libpyroctx.roctxProfilerResume(tid)
def getThreadId():
return libpyroctx.roctxGetThreadId()
def rangePush(msg):
return libpyroctx.roctxRangePush(msg)
def rangePop():
return libpyroctx.roctxRangePop()
def rangeStart(msg):
return libpyroctx.roctxRangeStart(msg) if msg is not None else None
def rangeStop(id=0):
return libpyroctx.roctxRangeStop(id) if id is not None else None
def nameOsThread(name):
return libpyroctx.roctxNameOsThread(name)
# def nameHsaAgent(name, agent):
# return libpyroctx.roctxNameHsaAgent(name, agent)
def nameHipDevice(name, device_id=0):
return libpyroctx.roctxNameHipDevice(name, device_id)
# def nameHipStream(name, stream):
# return libpyroctx.roctxNameHipStream(name, stream)
+101
Просмотреть файл
@@ -0,0 +1,101 @@
###############################################################################
# MIT License
#
# Copyright (c) 2023 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.
###############################################################################
from . import libpyroctx
from functools import wraps
class RoctxRange:
"""Provides decorators and context-manager for roctx range"""
def __init__(self, msg=None):
"""Initialize with a message"""
self.msg = msg
def __call__(self, func):
"""Decorator"""
@wraps(func)
def wrapper(*args, **kwargs):
libpyroctx.roctxRangePush(self.msg)
try:
return func(*args, **kwargs)
finally:
libpyroctx.roctxRangePop()
return wrapper
def __enter__(self):
"""Context manager start function"""
if self.msg is not None:
self.a = libpyroctx.roctxRangePush(self.msg)
return self.a
return self
def __exit__(self, exc_type, exc_value, tb):
"""Context manager stop function"""
if self.msg is not None:
libpyroctx.roctxRangePop()
if exc_type is not None and exc_value is not None and tb is not None:
import traceback
traceback.print_exception(exc_type, exc_value, tb, limit=5)
class RoctxProfiler:
"""Provides decorators and context-manager for roctx profiler"""
def __init__(self, tid=0):
"""Initialize with a tid"""
self.tid = tid
def __call__(self, func):
"""Decorator"""
@wraps(func)
def wrapper(*args, **kwargs):
libpyroctx.roctxProfilerResume(self.tid)
try:
return func(*args, **kwargs)
finally:
libpyroctx.roctxProfilerPause(self.tid)
return wrapper
def __enter__(self):
"""Context manager start function"""
self.a = libpyroctx.roctxProfilerResume(self.tid)
return self.a
def __exit__(self, exc_type, exc_value, tb):
"""Context manager stop function"""
libpyroctx.roctxProfilerPause(self.tid)
if exc_type is not None and exc_value is not None and tb is not None:
import traceback
traceback.print_exception(exc_type, exc_value, tb, limit=5)
+97
Просмотреть файл
@@ -0,0 +1,97 @@
// MIT License
//
// Copyright (c) 2022 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 "libpyroctx.hpp"
#include <rocprofiler-sdk-roctx/roctx.h>
#include <rocprofiler-sdk-roctx/types.h>
namespace py = ::pybind11;
PYBIND11_MODULE(libpyroctx, pyroctx)
{
py::doc("Rocprofiler-SDK ROCTx Python bindings");
pyroctx.def(
"roctxMark",
[](const std::string& _msg) { roctxMarkA(_msg.c_str()); },
"Mark an event in any attached profiler");
pyroctx.def(
"roctxProfilerPause",
[](roctx_thread_id_t tid) { return roctxProfilerPause(tid); },
"Pause data collection in any attached profiler");
pyroctx.def(
"roctxProfilerResume",
[](roctx_thread_id_t tid) { return roctxProfilerResume(tid); },
"Resume data collection in any attached profiler");
pyroctx.def(
"roctxGetThreadId",
[]() {
auto _tid = roctx_thread_id_t{0};
roctxGetThreadId(&_tid);
return _tid;
},
"Get the current thread ID");
pyroctx.def(
"roctxRangePush",
[](const std::string& _msg) { return roctxRangePushA(_msg.c_str()); },
"Start a new nested range");
pyroctx.def(
"roctxRangePop", []() { return roctxRangePop(); }, "Stop the current nested range");
pyroctx.def(
"roctxRangeStart",
[](const std::string& _msg) { return roctxRangeStartA(_msg.c_str()); },
"Start a process range");
pyroctx.def(
"roctxRangeStop", [](roctx_range_id_t id) { roctxRangeStop(id); }, "Stop a process range");
pyroctx.def(
"roctxNameOsThread",
[](const std::string& name) { return roctxNameOsThread(name.c_str()); },
"Label the current CPU OS thread with the provided name");
// pyroctx.def(
// "roctxNameHsaAgent",
// [](const std::string& name, const struct hsa_agent_s* agent) { return
// roctxNameHsaAgent(name.c_str(), agent); }, "Label the given HSA agent with the provided
// name");
pyroctx.def(
"roctxNameHipDevice",
[](const std::string& name, int device_id) {
return roctxNameHipDevice(name.c_str(), device_id);
},
"Label the given HIP device id with the provided name");
// pyroctx.def(
// "roctxNameHipStream",
// [](const std::string& name, const struct ihipStream_t* stream) { return
// roctxNameHipStream(name.c_str(), stream); }, "Label the given HIP stream with the
// provided name");
}
+36
Просмотреть файл
@@ -0,0 +1,36 @@
// MIT License
//
// Copyright (c) 2022 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 <pybind11/cast.h>
#include <pybind11/detail/common.h>
#include <pybind11/embed.h>
#include <pybind11/eval.h>
#include <pybind11/functional.h>
#include <pybind11/iostream.h>
#include <pybind11/numpy.h>
#include <pybind11/operators.h>
#include <pybind11/pybind11.h>
#include <pybind11/pytypes.h>
#include <pybind11/stl.h>
#include <pyerrors.h>
+228
Просмотреть файл
@@ -0,0 +1,228 @@
#
# functions/macros for python
#
include_guard(DIRECTORY)
macro(rocprofiler_reset_python3_cache)
foreach(
_VAR
_Python3_Compiler_REASON_FAILURE
_Python3_Development_REASON_FAILURE
_Python3_EXECUTABLE
_Python3_INCLUDE_DIR
_Python3_INTERPRETER_PROPERTIES
_Python3_INTERPRETER_SIGNATURE
_Python3_LIBRARY_RELEASE
_Python3_NumPy_REASON_FAILURE
Python3_EXECUTABLE
Python3_INCLUDE_DIR
Python3_INTERPRETER_ID
Python3_STDLIB
Python3_STDARCH
Python3_SITELIB
Python3_SOABI
${ARGN})
unset(${_VAR} CACHE)
unset(${_VAR})
endforeach()
endmacro()
macro(rocprofiler_find_python3 _VERSION)
rocprofiler_reset_python3_cache()
if("${_VERSION}" MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$")
find_package(Python3 ${_VERSION} EXACT ${_ARGN} REQUIRED MODULE
COMPONENTS Interpreter Development)
elseif("${_VERSION}" MATCHES "^([0-9]+)\\.([0-9]+)$")
find_package(Python3 ${_VERSION}.0...${_VERSION}.999 ${_ARGN} REQUIRED MODULE
COMPONENTS Interpreter Development)
else()
message(
FATAL_ERROR
"Invalid Python3 version (${_VERSION}). Specify <MAJOR>.<MINOR> or <MAJOR>.<MINOR>.<PATCH>"
)
endif()
endmacro()
function(get_default_python_version _VAR)
rocprofiler_reset_python3_cache()
find_package(Python3 3.6 ${_ARGN} REQUIRED MODULE COMPONENTS Interpreter Development)
if(Python3_FOUND)
set(${_VAR}
${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}
PARENT_SCOPE)
endif()
rocprofiler_reset_python3_cache()
endfunction()
function(rocprofiler_roctx_python_bindings _VERSION)
message(
STATUS "Creating rocprofiler-sdk roctx python bindings for python ${_VERSION}")
rocprofiler_find_python3(${_VERSION})
set(roctx_PYTHON_INSTALL_DIRECTORY
${CMAKE_INSTALL_LIBDIR}/python${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}/site-packages/roctx
)
set(roctx_PYTHON_OUTPUT_DIRECTORY
${PROJECT_BINARY_DIR}/${roctx_PYTHON_INSTALL_DIRECTORY})
set(roctx_PYTHON_SOURCES __init__.py context_decorators.py)
foreach(_SOURCE ${roctx_PYTHON_SOURCES})
configure_file(${CMAKE_CURRENT_LIST_DIR}/${_SOURCE}
${roctx_PYTHON_OUTPUT_DIRECTORY}/${_SOURCE} COPYONLY)
install(
FILES ${roctx_PYTHON_OUTPUT_DIRECTORY}/${_SOURCE}
DESTINATION ${roctx_PYTHON_INSTALL_DIRECTORY}
COMPONENT core)
endforeach()
add_library(rocprofiler-sdk-roctx-python-bindings-${_VERSION} MODULE)
target_sources(rocprofiler-sdk-roctx-python-bindings-${_VERSION}
PRIVATE libpyroctx.cpp)
target_include_directories(rocprofiler-sdk-roctx-python-bindings-${_VERSION} SYSTEM
PRIVATE ${Python3_INCLUDE_DIRS})
target_link_libraries(
rocprofiler-sdk-roctx-python-bindings-${_VERSION}
PRIVATE rocprofiler-sdk-roctx::rocprofiler-sdk-roctx-shared-library
rocprofiler-sdk::rocprofiler-sdk-pybind11 ${Python3_LIBRARIES})
set_target_properties(
rocprofiler-sdk-roctx-python-bindings-${_VERSION}
PROPERTIES OUTPUT_NAME libpyroctx
RUNTIME_OUTPUT_DIRECTORY ${roctx_PYTHON_OUTPUT_DIRECTORY}
LIBRARY_OUTPUT_DIRECTORY ${roctx_PYTHON_OUTPUT_DIRECTORY}
ARCHIVE_OUTPUT_DIRECTORY ${roctx_PYTHON_OUTPUT_DIRECTORY}
PDB_OUTPUT_DIRECTORY ${roctx_PYTHON_OUTPUT_DIRECTORY}
PREFIX ""
SUFFIX ".${Python3_SOABI}${CMAKE_SHARED_LIBRARY_SUFFIX}"
BUILD_RPATH "${DEFAULT_PYTHON_RPATH}"
INSTALL_RPATH "${DEFAULT_PYTHON_RPATH}")
install(
TARGETS rocprofiler-sdk-roctx-python-bindings-${_VERSION}
DESTINATION ${roctx_PYTHON_INSTALL_DIRECTORY}
COMPONENT core)
endfunction()
function(rocprofiler_rocpd_python_bindings_target_sources _VERSION)
target_sources(rocprofiler-sdk-rocpd-python-bindings-${_VERSION} ${ARGN})
endfunction()
function(rocprofiler_rocpd_python_bindings _VERSION)
message(
STATUS "Creating rocprofiler-sdk rocpd python bindings for python ${_VERSION}")
rocprofiler_find_python3(${_VERSION})
set(rocpd_PYTHON_INSTALL_DIRECTORY
${CMAKE_INSTALL_LIBDIR}/python${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}/site-packages/rocpd
)
set(rocpd_PYTHON_OUTPUT_DIRECTORY
${PROJECT_BINARY_DIR}/${rocpd_PYTHON_INSTALL_DIRECTORY})
set(rocpd_PYTHON_SOURCES
chrome_tracing.py
csv.py
importer.py
__init__.py
__main__.py
output_config.py
pftrace.py
schema.py
time_window.py)
set(rocpd_SCHEMA_SOURCES
schema_data/data_views.sql schema_data/marker_views.sql
schema_data/rocpd_indexes.sql schema_data/rocpd_tables.sql
schema_data/rocpd_views.sql schema_data/summary_views.sql)
foreach(_SOURCE ${rocpd_PYTHON_SOURCES})
configure_file(${CMAKE_CURRENT_LIST_DIR}/${_SOURCE}
${rocpd_PYTHON_OUTPUT_DIRECTORY}/${_SOURCE} COPYONLY)
install(
FILES ${rocpd_PYTHON_OUTPUT_DIRECTORY}/${_SOURCE}
DESTINATION ${rocpd_PYTHON_INSTALL_DIRECTORY}
COMPONENT core)
endforeach()
foreach(_SOURCE ${rocpd_SCHEMA_SOURCES})
configure_file(${CMAKE_CURRENT_LIST_DIR}/${_SOURCE}
${rocpd_PYTHON_OUTPUT_DIRECTORY}/${_SOURCE} COPYONLY)
install(
FILES ${rocpd_PYTHON_OUTPUT_DIRECTORY}/${_SOURCE}
DESTINATION ${rocpd_PYTHON_INSTALL_DIRECTORY}/schema_data
COMPONENT core)
endforeach()
add_library(rocprofiler-sdk-rocpd-python-bindings-${_VERSION} MODULE)
target_sources(
rocprofiler-sdk-rocpd-python-bindings-${_VERSION}
PRIVATE libpyrocpd.cpp libpyrocpd.hpp
$<TARGET_OBJECTS:rocprofiler-sdk::rocprofiler-sdk-object-library>)
target_include_directories(rocprofiler-sdk-rocpd-python-bindings-${_VERSION} SYSTEM
PRIVATE ${Python3_INCLUDE_DIRS})
target_link_libraries(
rocprofiler-sdk-rocpd-python-bindings-${_VERSION}
PRIVATE rocprofiler-sdk::rocprofiler-sdk-headers
rocprofiler-sdk::rocprofiler-sdk-build-flags
rocprofiler-sdk::rocprofiler-sdk-memcheck
rocprofiler-sdk::rocprofiler-sdk-common-library
rocprofiler-sdk::rocprofiler-sdk-output-library
rocprofiler-sdk::rocprofiler-sdk-cereal
rocprofiler-sdk::rocprofiler-sdk-perfetto
rocprofiler-sdk::rocprofiler-sdk-otf2
rocprofiler-sdk::rocprofiler-sdk-sqlite3
rocprofiler-sdk::rocprofiler-sdk-pybind11
rocprofiler-sdk::rocprofiler-sdk-gotcha
rocprofiler-sdk::rocprofiler-sdk-dw
rocprofiler-sdk::rocprofiler-sdk-static-library
${Python3_LIBRARIES})
set_target_properties(
rocprofiler-sdk-rocpd-python-bindings-${_VERSION}
PROPERTIES OUTPUT_NAME libpyrocpd
RUNTIME_OUTPUT_DIRECTORY ${rocpd_PYTHON_OUTPUT_DIRECTORY}
LIBRARY_OUTPUT_DIRECTORY ${rocpd_PYTHON_OUTPUT_DIRECTORY}
ARCHIVE_OUTPUT_DIRECTORY ${rocpd_PYTHON_OUTPUT_DIRECTORY}
PDB_OUTPUT_DIRECTORY ${rocpd_PYTHON_OUTPUT_DIRECTORY}
PREFIX ""
SUFFIX ".${Python3_SOABI}${CMAKE_SHARED_LIBRARY_SUFFIX}"
BUILD_RPATH "${DEFAULT_PYTHON_RPATH}"
INSTALL_RPATH "${DEFAULT_PYTHON_RPATH}")
install(
TARGETS rocprofiler-sdk-rocpd-python-bindings-${_VERSION}
DESTINATION ${rocpd_PYTHON_INSTALL_DIRECTORY}
COMPONENT core)
endfunction()
function(rocprofiler_rocpd_python_packaging _VERSION)
message(
STATUS "Creating rocprofiler-sdk rocpd python packaging for python ${_VERSION}")
rocprofiler_find_python3(${_VERSION})
add_custom_target(
rocprofiler-sdk-rocpd-${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR} ALL
${Python3_EXECUTABLE}
-m
pip
install
-q
-q
--prefix
${PROJECT_BINARY_DIR}
-I
${CMAKE_CURRENT_BINARY_DIR}
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
COMMENT
"Packaging rocpd for python${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}..."
)
install(
DIRECTORY
${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/python${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}
DESTINATION ${CMAKE_INSTALL_LIBDIR}
USE_SOURCE_PERMISSIONS
COMPONENT core)
endfunction()