SDK: Agent UUIDs, agent runtime visibility, kernel symbol address (#154)

* [DO NOT MERGE] Misc UUID updates

- this is WIP

* Agent visibility

- Support for ROCR_VISIBLE_DEVICES, HIP_VISIBLE_DEVICES, CUDA_VISIBLE_DEVICES, GPU_DEVICE_ORDINAL

* Update CHANGELOG

* tweak to rocprofiler_agent_runtime_visiblity_t

* Code object kernel address

- new fields in code_object_kernel_symbol_register_data_t
  - kernel_code_entry_byte_offset
  - kernel_address

* Support ROCR_VISIBLE_DEVICES reordering devices for HIP

* Addressed code review changes

---------

Co-authored-by: Jonathan R. Madsen <jonathanrmadsen@gmail.com>
This commit is contained in:
Madsen, Jonathan
2025-02-11 14:36:23 -06:00
committed by GitHub
parent 3071199386
commit 6246ec4040
14 changed files with 914 additions and 94 deletions
+53 -13
View File
@@ -97,6 +97,26 @@ typedef struct rocprofiler_agent_mem_bank_t
uint64_t size_in_bytes; ///< physical memory size of the memory range in bytes
} rocprofiler_agent_mem_bank_t;
/**
* @brief Provides an *estimate* about the runtime visibility of an agent based on the environment
* variables (ROCR_VISIBLE_DEVICES, HIP_VISIBLE_DEVICES, GPU_DEVICE_ORDINAL, CUDA_VISIBLE_DEVICES).
* Reference: https://rocm.docs.amd.com/en/latest/conceptual/gpu-isolation.html
*/
typedef struct rocprofiler_agent_runtime_visiblity_t
{
// Note: HSA == ROCR
uint32_t hsa : 1; ///> if not visible to HSA, agent not visible to anything built on HSA
uint32_t hip : 1; ///> Built on HSA
uint32_t rccl : 1; ///> Built on HIP
uint32_t rocdecode : 1; ///> Built on HIP
uint32_t reserved : 28;
} rocprofiler_agent_runtime_visiblity_t;
ROCPROFILER_CXX_CODE(
static_assert(
sizeof(rocprofiler_agent_runtime_visiblity_t) == sizeof(uint32_t),
"Increasing the size of the rocprofiler_agent_runtime_visiblity_t is not permitted");)
/**
* @brief Stores the properties of an agent (CPU, GPU, etc.)
*
@@ -180,20 +200,33 @@ typedef struct rocprofiler_agent_v0_t
///< dimension of a work-group.
rocprofiler_dim3_t grid_max_dim; ///< GPU only. Maximum number of work-items of each dimension
///< of a grid.
const rocprofiler_agent_mem_bank_t* mem_banks;
const rocprofiler_agent_cache_t* caches;
const rocprofiler_agent_io_link_t* io_links;
const char* name; ///< Name of the agent. Will be identical to product name for CPU
const char* vendor_name; ///< Vendor of agent (will be AMD)
const char* product_name; ///< Marketing name
const char* model_name; ///< GPU only. Will be something like vega20, mi200, etc.
uint32_t node_id; ///< Node sequence number. This will be equivalent to the HSA-runtime
///< HSA_AMD_AGENT_INFO_DRIVER_NODE_ID property
int32_t logical_node_id; ///< Logical sequence number. This will always be [0..N) where N is
///< the total number of agents
int32_t logical_node_type_id;
int32_t reserved_padding0; ///< padding logical_node_id to 64 bytes
const rocprofiler_agent_mem_bank_t* mem_banks;
const rocprofiler_agent_cache_t* caches;
const rocprofiler_agent_io_link_t* io_links;
const char* name;
const char* vendor_name; ///< Vendor of agent (will be AMD)
const char* product_name; ///< Marketing name
const char* model_name;
uint32_t node_id;
int32_t logical_node_id;
int32_t logical_node_type_id;
rocprofiler_agent_runtime_visiblity_t runtime_visibility;
rocprofiler_uuid_t uuid; ///< GPU only. Universally unique identifier.
/// @var name
/// @brief Name of the agent. Will be identical to product name for CPU
///
/// @var model_name
/// @brief GPU only. Will be something like vega20, mi200, etc.
///
/// @var node_id
/// @brief Node sequence number. This will be equivalent to the HSA-runtime
/// HSA_AMD_AGENT_INFO_DRIVER_NODE_ID property
///
/// @var logical_node_id
/// @brief Logical sequence number. This will always be [0..N) where N is the total number of
/// agents
///
/// @var logical_node_type_id
/// @brief Logical sequence number with respect to other agents of same type. This will always
/// be [0..N) where N is the total number of X agents (where X is a ::rocprofiler_agent_type_t
@@ -207,6 +240,13 @@ typedef struct rocprofiler_agent_v0_t
/// then then CPU node_ids 0 and 2 would have logical_node_type_id values of 0 and 1,
/// respectively, and GPU node_ids 1 and 3 would also have logical_node_type_id values of 0
/// and 1.
///
/// @var runtime_visibility
/// @brief See @rocprofiler_runtime_library_t. This is an estimate about whether this agent will
/// be visible for the runtimes, e.g. if (agent.runtime_visibility & ROCPROFILER_HIP_LIBRARY) !=
/// 0 then we believe this agent will be visible to the HIP library. However, this is an
/// estimate and we cannot be certain until the HIP runtime is initialized. This will always be
/// true for CPU agents.
} rocprofiler_agent_v0_t;
typedef rocprofiler_agent_v0_t rocprofiler_agent_t;
@@ -124,22 +124,36 @@ typedef struct
*/
typedef struct
{
uint64_t size; ///< size of this struct
uint64_t code_object_id; ///< unique code object identifier
rocprofiler_agent_id_t rocp_agent; ///< The agent on which this loaded code object is loaded
hsa_agent_t hsa_agent; ///< The agent on which this loaded code object is loaded
const char* uri; ///< The URI name from which the code object was loaded
uint64_t load_base; ///< The base memory address at which the code object is loaded. This is
///< the base address of the allocation for the lowest addressed segment of
///< the code object that is loaded. Note that any non-loaded segments
///< before the first loaded segment are ignored.
uint64_t load_size; ///< The byte size of the loaded code objects contiguous memory allocation.
int64_t load_delta; ///< The signed byte address difference of the memory address at which the
///< code object is loaded minus the virtual address specified in the code
///< object that is loaded.
rocprofiler_code_object_storage_type_t
storage_type; ///< storage type of the code object reader used to load the loaded code
///< object
uint64_t size; ///< size of this struct
uint64_t code_object_id; ///< unique code object identifier
union
{
rocprofiler_agent_id_t rocp_agent; ///< Deprecated. Renamed to agent_id
rocprofiler_agent_id_t agent_id; ///< The agent on which this loaded code object is loaded
};
hsa_agent_t hsa_agent; ///< Deprecated. The agent on which this loaded code object is loaded
const char* uri; ///< The URI name from which the code object was loaded
uint64_t load_base;
uint64_t load_size;
int64_t load_delta;
rocprofiler_code_object_storage_type_t storage_type;
/// @var load_base
/// @brief The base memory address at which the code object is loaded. This is the base address
/// of the allocation for the lowest addressed segment of the code object that is loaded. Note
/// that any non-loaded segments before the first loaded segment are ignored.
///
/// @var load_size
/// @brief The byte size of the loaded code objects contiguous memory allocation.
///
/// @var load_delta
/// @brief The signed byte address difference of the memory address at which the code object is
/// loaded minus the virtual address specified in the code object that is loaded.
///
/// @var storage_type
/// @brief storage type of the code object reader used to load the loaded code object
///
union
{
struct
@@ -171,26 +185,47 @@ typedef struct
* @brief ROCProfiler Code Object Kernel Symbol Tracer Callback Record.
*
*/
typedef struct
typedef struct rocprofiler_callback_tracing_code_object_kernel_symbol_register_data_t
{
uint64_t size; ///< size of this struct
uint64_t kernel_id; ///< unique symbol identifier value
uint64_t code_object_id; ///< parent unique code object identifier
const char* kernel_name; ///< name of the kernel
uint64_t kernel_object; ///< kernel object handle, used in the kernel dispatch packet
uint32_t kernarg_segment_size; ///< size of memory (in bytes) allocated for kernel arguments.
///< Will be multiple of 16
uint32_t kernarg_segment_alignment; ///< Alignment (in bytes) of the buffer used to pass
///< arguments to the kernel
uint32_t group_segment_size; ///< Size of static group segment memory required by the kernel
///< (per work-group), in bytes. AKA: LDS size
uint32_t private_segment_size; ///< Size of static private, spill, and arg segment memory
///< required by this kernel (per work-item), in bytes. AKA:
///< scratch size
uint32_t sgpr_count; ///< Scalar general purpose register count
uint32_t arch_vgpr_count; ///< Architecture vector general purpose register count
uint32_t accum_vgpr_count; ///< Accum vector general purpose register count
uint64_t size; ///< size of this struct
uint64_t kernel_id; ///< unique symbol identifier value
uint64_t code_object_id; ///< parent unique code object identifier
const char* kernel_name; ///< name of the kernel
uint64_t kernel_object;
uint32_t kernarg_segment_size;
uint32_t kernarg_segment_alignment;
uint32_t group_segment_size;
uint32_t private_segment_size;
uint32_t sgpr_count; ///< Scalar general purpose register count
uint32_t arch_vgpr_count; ///< Architecture vector general purpose register count
uint32_t accum_vgpr_count; ///< Accum vector general purpose register count
int64_t kernel_code_entry_byte_offset;
rocprofiler_address_t kernel_address;
/// @var kernel_object
/// @brief kernel object handle, used in the kernel dispatch packet
///
/// @var kernarg_segment_size
/// @brief size of memory (in bytes) allocated for kernel arguments. Will be multiple of 16
///
/// @var kernarg_segment_alignment
/// @brief Alignment (in bytes) of the buffer used to pass arguments to the kernel
///
/// @var group_segment_size
/// @brief Size of static group segment memory required by the kernel (per work-group), in
/// bytes. AKA: LDS size
///
/// @var private_segment_size
/// @brief Size of static private, spill, and arg segment memory required by this kernel (per
/// work-item), in bytes. AKA: scratch size
///
/// @var kernel_code_entry_byte_offset
/// @brief Relative offset from kernel_object address to calculate the first address of a
/// kernel.
///
/// @var kernel_address
/// @brief The first address of a kernel. Useful for PC sampling.
///
} rocprofiler_callback_tracing_code_object_kernel_symbol_register_data_t;
// rename struct
@@ -151,8 +151,7 @@ save(ArchiveT& ar, rocprofiler_callback_tracing_code_object_load_data_t data)
{
ROCP_SDK_SAVE_DATA_FIELD(size);
ROCP_SDK_SAVE_DATA_FIELD(code_object_id);
ROCP_SDK_SAVE_DATA_FIELD(rocp_agent);
ROCP_SDK_SAVE_DATA_FIELD(hsa_agent);
ROCP_SDK_SAVE_DATA_FIELD(agent_id);
ROCP_SDK_SAVE_DATA_CSTR(uri);
ROCP_SDK_SAVE_DATA_FIELD(load_base);
ROCP_SDK_SAVE_DATA_FIELD(load_size);
@@ -185,6 +184,8 @@ save(ArchiveT& ar, rocprofiler_callback_tracing_code_object_kernel_symbol_regist
ROCP_SDK_SAVE_DATA_FIELD(sgpr_count);
ROCP_SDK_SAVE_DATA_FIELD(arch_vgpr_count);
ROCP_SDK_SAVE_DATA_FIELD(accum_vgpr_count);
ROCP_SDK_SAVE_DATA_FIELD(kernel_code_entry_byte_offset);
ROCP_SDK_SAVE_DATA_FIELD(kernel_address);
}
template <typename ArchiveT>
@@ -23,6 +23,7 @@
#pragma once
#include <cstdint>
#include <iomanip>
#include <sstream>
@@ -36,8 +37,14 @@ template <typename Tp>
auto
as_hex(Tp val, size_t width = 0)
{
uintptr_t _uintp_val = 0;
if constexpr(std::is_pointer<Tp>::value)
_uintp_val = reinterpret_cast<uintptr_t>(val);
else
_uintp_val = val;
auto ss = std::stringstream{};
ss << "0x" << std::hex << std::setfill('0') << std::setw(width) << val;
ss << "0x" << std::hex << std::setfill('0') << std::setw(width) << _uintp_val;
return ss.str();
}
} // namespace utility
+10
View File
@@ -532,6 +532,16 @@ typedef union rocprofiler_address_t
void* ptr; ///< usage example: generic form of address
} rocprofiler_address_t;
/**
* @brief Stores UUID for devices.
*
*/
typedef union rocprofiler_uuid_t
{
uint64_t value; ///< numerical value
void* bytes; ///< uuid in hexadecimal
} rocprofiler_uuid_t;
//--------------------------------------------------------------------------------------//
//
// STRUCTS