2024-03-08 08:35:16 +05:30
# Tool Library
2023-11-28 10:04:37 -06:00
## Rocprofiler and ROCm Runtimes Design
The ROCm runtimes are now designed to directly communicate with a new library called rocprofiler-register during their initialization. This library does cursory checks
for whether any tools have indicated they want rocprofiler support via detection of one or more instances of a symbol named `rocprofiler_configure` (which is provided by
2024-04-14 14:35:00 -05:00
the tool libraries) and/or the `ROCP_TOOL_LIBRARIES` environment variable. This design dramatically improves upon previous designs, which relied solely on
a tool racing to set runtime-specific environment variables (e.g., `HSA_TOOLS_LIB` ) before the runtime initialization.
2023-11-28 10:04:37 -06:00
## Tool Library Design
When a tool has `rocprofiler_configure` visible in its symbol table, rocprofiler will invoke this function and provide information regarding
2024-04-14 14:35:00 -05:00
the version of rocprofiler, which invokes the function, how many tools have already been invoked, and a unique identifier for the tool. The tool
2023-11-28 10:04:37 -06:00
returns a pointer to a `rocprofiler_tool_configure_result_t` struct, which, if non-null, can provide rocprofiler with the function it should
2024-04-14 14:35:00 -05:00
call for tool initialization (i.e., the opportunity for context creation), and a function should call when rocprofiler is finalized, and a pointer
to any data that the rocprofiler should provide back to the tool when it calls the initialization and finalization functions.
2023-11-28 10:04:37 -06:00
2024-04-14 14:35:00 -05:00
Rocprofiler provides a `rocprofiler/registration.h` header file, which forward declares the `rocprofiler_configure` function with the necessary
2023-11-28 10:04:37 -06:00
compiler function attributes to ensure that the symbol is publicly visible.
```cpp
2023-11-29 20:43:18 -06:00
#include <rocprofiler-sdk/registration.h>
2023-11-28 10:04:37 -06:00
namespace
{
// saves the data provided to rocprofiler_configure
struct ToolData
{
uint32_t version ;
const char * runtime_version ;
uint32_t priority ;
rocprofiler_client_id_t client_id ;
};
// tool initialization function
int
tool_init ( rocprofiler_client_finalize_t fini_func ,
void * tool_data_v );
// tool finalization function
void
tool_fini ( void * tool_data_v );
}
extern "C"
{
rocprofiler_tool_configure_result_t *
rocprofiler_configure ( uint32_t version ,
const char * runtime_version ,
uint32_t priority ,
rocprofiler_client_id_t * client_id )
{
2024-04-14 14:35:00 -05:00
//If not the first tool to register, indicate that the tool doesn't want to do anything
2023-11-28 10:04:37 -06:00
if ( priority > 0 ) return nullptr ;
2024-04-14 14:35:00 -05:00
// (optional) Provide a name for this tool to rocprofiler
2023-11-28 10:04:37 -06:00
client_id -> name = "ExampleTool" ;
// (optional) create configure data
static auto data = ToolData { version ,
runtime_version ,
priority ,
client_id };
// construct configure result
static auto cfg =
rocprofiler_tool_configure_result_t { sizeof ( rocprofiler_tool_configure_result_t ),
& tool_init ,
& tool_fini ,
static_cast < void *> ( & data ) };
return & cfg ;
}
```
## Tool Initialization
2024-04-14 14:35:00 -05:00
> ***NOTE: rocprofiler does NOT support calls to any runtime function (HSA, HIP, etc.) during tool initialization.***
2023-11-28 10:04:37 -06:00
> ***Invoking any functions from the runtimes will result in a deadlock.***
2024-04-14 14:35:00 -05:00
For each tool that contains a `rocprofiler_configure` function and returns a non-null pointer to a `rocprofiler_tool_configure_result_t` struct,
2023-11-28 10:04:37 -06:00
rocprofiler will invoke the `initialize` callback after completing the scan for all `rocprofiler_configure` symbols. In other words, rocprofiler
collects all of the `rocprofiler_tool_configure_result_t` instances before invoking the `initialize` member of any of these instances.
When rocprofiler invokes this function in a tool, this is the opportunity to create contexts:
```cpp
2023-11-29 20:43:18 -06:00
#include <rocprofiler-sdk/rocprofiler.h>
2023-11-28 10:04:37 -06:00
namespace
{
int
tool_init ( rocprofiler_client_finalize_t fini_func ,
void * data_v )
{
// create a context
auto ctx = rocprofiler_context_id_t {};
rocprofiler_create_context ( & ctx );
// ... associate services with context ...
// start the context (optional)
rocprofiler_start_context ( ctx );
return 0 ;
}
}
```
Although not strictly necessary, it is recommended that tools store the context handle(s) to control the data collection of the services associated with the context.
## Tool Finalization
2024-04-14 14:35:00 -05:00
When the user-provided `initialize` callback is invoked, rocprofiler will provide a function pointer of type `rocprofiler_client_finalize_t` .
2023-11-28 10:04:37 -06:00
This function pointer can be invoked by the tool to explicitly invoke the `finalize` callback from the `rocprofiler_tool_configure_result_t` instance:
```cpp
2023-11-29 20:43:18 -06:00
#include <rocprofiler-sdk/rocprofiler.h>
2023-11-28 10:04:37 -06:00
namespace
{
int
tool_init ( rocprofiler_client_finalize_t fini_func ,
void * data_v )
{
// ... see initialization section ...
2024-04-14 14:35:00 -05:00
// function, which finalizes the tool after 10 seconds
2023-11-28 10:04:37 -06:00
auto explicit_finalize = []( rocprofiler_client_finalize_t finalizer ,
rocprofiler_client_id_t * client_id )
{
std :: this_thread :: sleep_for ( std :: chrono :: seconds { 10 });
finalizer ( client_id );
};
// start the context
rocprofiler_start_context ( ctx );
// dispatch a background thread to explicitly finalize after 10 seconds
std :: thread { explicit_finalize , fini_func , static_cast < ToolData *> ( data_v ) -> client_id }. detach ();
return 0 ;
}
}
```
2024-04-14 14:35:00 -05:00
Otherwise, the rocprofiler will invoke the `finalize` callback via an `atexit` handler.
2023-11-28 10:04:37 -06:00
## Agent Information
## Contexts
## Configuring Services
## Synchronous Callbacks
2024-04-14 14:35:00 -05:00
## Asynchronous Callbacks for Buffers
2023-11-28 10:04:37 -06:00
## Recommendations
## Full `rocprofiler_configure` Sample
All of the snippets from the previous sections have been combined here for convenience.
```cpp
2023-11-29 20:43:18 -06:00
#include <rocprofiler-sdk/registration.h>
2023-11-28 10:04:37 -06:00
namespace
{
struct rocp_tool_data
{
uint32_t version ;
const char * runtime_version ;
uint32_t priority ;
rocprofiler_client_id_t client_id ;
rocprofiler_client_finalize_t finalizer ;
std :: vector < rocprofiler_context_id_t > contexts ;
};
void
tool_tracing_callback ( rocprofiler_callback_tracing_record_t record ,
rocprofiler_user_data_t * user_data ,
void * callback_data );
int
tool_init ( rocprofiler_client_finalize_t fini_func ,
void * tool_data_v )
{
rocp_tool_data * tool_data = static_cast < rocp_tool_data *> ( tool_data_v );
2024-04-14 14:35:00 -05:00
// Save the finalizer function
2023-11-28 10:04:37 -06:00
tool_data -> finalizer = fini_func ;
// create a context
auto ctx = rocprofiler_context_id_t {};
rocprofiler_create_context ( & ctx );
2024-04-14 14:35:00 -05:00
// Save your contexts
2023-11-28 10:04:37 -06:00
tool_data -> contexts . emplace_back ( ctx );
// associate code object tracing with this context
rocprofiler_configure_callback_tracing_service (
ctx ,
ROCPROFILER_CALLBACK_TRACING_CODE_OBJECT ,
nullptr ,
0 ,
tool_tracing_callback ,
tool_data );
// ... associate services with contexts ...
return 0 ;
}
void
tool_fini ( void * tool_data );
}
extern "C"
{
rocprofiler_tool_configure_result_t *
rocprofiler_configure ( uint32_t version ,
const char * runtime_version ,
uint32_t priority ,
rocprofiler_client_id_t * client_id )
{
2024-04-14 14:35:00 -05:00
// (optional) Provide a name for this tool to rocprofiler
2023-11-28 10:04:37 -06:00
client_id -> name = "ExampleTool" ;
// info provided back to tool_init and tool_fini
auto * my_tool_data = new rocp_tool_data { version ,
runtime_version ,
priority ,
client_id ,
nullptr };
// create configure data
static auto cfg =
rocprofiler_tool_configure_result_t { sizeof ( rocprofiler_tool_configure_result_t ),
& tool_init ,
& tool_fini ,
my_tool_data };
return & cfg ;
}
```