Thread trace and Trace Decoder API tests and samples (#416)

* Adding test and samples to decoder

* Fix sample

* Formatting

* Fix multi test

* Disable sample

* Fix tests

* Format

* Version fix

* Locking the decoder

* Add atomic

* Review comments

* Format

* Adding readme

* merge conflict and adding PCS+ATT test

* Review comments

* Properly disable PCS test

* Update tests/rocprofv3/advanced-thread-trace/CMakeLists.txt

* Adding back env var test

* Name fix

* Preload sample

* Addressing review comments

* Update docs

---------

Co-authored-by: Giovanni Baraldi <gbaraldi@amd.com>
このコミットが含まれているのは:
Baraldi, GiovanniとGiovanni Baraldi authored and GitHub committed 2025-07-22 20:08:12 -05:00
1 親 bf0fad1d54
コミット e898079a13
22ファイル変更
+982 -404

検索条件に一致するファイルはありません

+1 -1
ファイルの表示
@@ -188,7 +188,7 @@ To decode the raw thread trace data, create and initialize a Trace Decoder:
.. code-block:: cpp
rocprofiler_thread_trace_decoder_handle_t decoder{};
rocprofiler_thread_trace_decoder_id_t decoder{};
// Create the Trace Decoder with the path to the decoder library
ROCPROFILER_CALL(
+2
ファイルの表示
@@ -23,6 +23,7 @@
#pragma once
#include <rocprofiler-sdk/experimental/thread-trace/trace_decoder.h>
#include <rocprofiler-sdk/fwd.h>
#include <rocprofiler-sdk/hsa.h>
#include <rocprofiler-sdk/internal_threading.h>
@@ -70,6 +71,7 @@ ROCPROFILER_CXX_SPECIALIZE_HANDLE_HASHER(hsa_signal_t)
ROCPROFILER_CXX_SPECIALIZE_HANDLE_HASHER(hsa_executable_t)
ROCPROFILER_CXX_SPECIALIZE_HANDLE_HASHER(hsa_region_t)
ROCPROFILER_CXX_SPECIALIZE_HANDLE_HASHER(hsa_amd_memory_pool_t)
ROCPROFILER_CXX_SPECIALIZE_HANDLE_HASHER(rocprofiler_thread_trace_decoder_id_t)
#undef ROCPROFILER_CXX_SPECIALIZE_HANDLE_HASHER
} // namespace std
+6
ファイルの表示
@@ -26,6 +26,7 @@
#include <rocprofiler-sdk/agent.h>
#include <rocprofiler-sdk/counters.h>
#include <rocprofiler-sdk/defines.h>
#include <rocprofiler-sdk/experimental/thread-trace/trace_decoder.h>
#include <rocprofiler-sdk/fwd.h>
#include <rocprofiler-sdk/hsa.h>
#include <rocprofiler-sdk/internal_threading.h>
@@ -148,6 +149,7 @@ ROCPROFILER_CXX_DECLARE_OPERATORS(const rocprofiler_counter_record_dimension_inf
ROCPROFILER_CXX_DECLARE_OPERATORS(const rocprofiler_counter_record_dimension_instance_info_t&)
ROCPROFILER_CXX_DECLARE_OPERATORS(const rocprofiler_counter_dimension_info_t&)
ROCPROFILER_CXX_DECLARE_OPERATORS(rocprofiler_version_triplet_t)
ROCPROFILER_CXX_DECLARE_OPERATORS(rocprofiler_thread_trace_decoder_id_t)
// definitions of operator==
ROCPROFILER_CXX_DEFINE_EQ_HANDLE_OPERATOR(rocprofiler_context_id_t)
@@ -164,6 +166,7 @@ ROCPROFILER_CXX_DEFINE_EQ_HANDLE_OPERATOR(hsa_signal_t)
ROCPROFILER_CXX_DEFINE_EQ_HANDLE_OPERATOR(hsa_executable_t)
ROCPROFILER_CXX_DEFINE_EQ_HANDLE_OPERATOR(hsa_region_t)
ROCPROFILER_CXX_DEFINE_EQ_HANDLE_OPERATOR(hsa_amd_memory_pool_t)
ROCPROFILER_CXX_DEFINE_EQ_HANDLE_OPERATOR(rocprofiler_thread_trace_decoder_id_t)
inline bool
operator==(const rocprofiler_agent_v0_t& lhs, const rocprofiler_agent_v0_t& rhs)
@@ -241,6 +244,7 @@ ROCPROFILER_CXX_DEFINE_NE_OPERATOR(rocprofiler_dim3_t)
ROCPROFILER_CXX_DEFINE_NE_OPERATOR(hsa_region_t)
ROCPROFILER_CXX_DEFINE_NE_OPERATOR(hsa_amd_memory_pool_t)
ROCPROFILER_CXX_DEFINE_NE_OPERATOR(rocprofiler_version_triplet_t)
ROCPROFILER_CXX_DEFINE_NE_OPERATOR(rocprofiler_thread_trace_decoder_id_t)
// definitions of operator<
ROCPROFILER_CXX_DEFINE_LT_HANDLE_OPERATOR(rocprofiler_context_id_t)
@@ -257,6 +261,7 @@ ROCPROFILER_CXX_DEFINE_LT_HANDLE_OPERATOR(hsa_signal_t)
ROCPROFILER_CXX_DEFINE_LT_HANDLE_OPERATOR(hsa_executable_t)
ROCPROFILER_CXX_DEFINE_LT_HANDLE_OPERATOR(hsa_region_t)
ROCPROFILER_CXX_DEFINE_LT_HANDLE_OPERATOR(hsa_amd_memory_pool_t)
ROCPROFILER_CXX_DEFINE_LT_HANDLE_OPERATOR(rocprofiler_thread_trace_decoder_id_t)
inline bool
operator<(const rocprofiler_counter_record_dimension_info_t& lhs,
@@ -334,6 +339,7 @@ ROCPROFILER_CXX_DEFINE_COMPARE_OPERATORS(rocprofiler_dim3_t)
ROCPROFILER_CXX_DEFINE_COMPARE_OPERATORS(hsa_region_t)
ROCPROFILER_CXX_DEFINE_COMPARE_OPERATORS(hsa_amd_memory_pool_t)
ROCPROFILER_CXX_DEFINE_COMPARE_OPERATORS(rocprofiler_version_triplet_t)
ROCPROFILER_CXX_DEFINE_COMPARE_OPERATORS(rocprofiler_thread_trace_decoder_id_t)
// cleanup defines
#undef ROCPROFILER_CXX_DECLARE_OPERATORS
+13 -13
ファイルの表示
@@ -36,10 +36,10 @@ ROCPROFILER_EXTERN_C_INIT
/**
* @brief Handle containing a loaded rocprof-trace-decoder and a decoder state.
*/
typedef struct rocprofiler_thread_trace_decoder_handle_t
typedef struct rocprofiler_thread_trace_decoder_id_t
{
uint64_t handle;
} rocprofiler_thread_trace_decoder_handle_t;
} rocprofiler_thread_trace_decoder_id_t;
/**
* @brief Initializes Trace Decoder library with a library search path
@@ -51,7 +51,7 @@ typedef struct rocprofiler_thread_trace_decoder_handle_t
* @retval ::ROCPROFILER_STATUS_SUCCESS Handle created
*/
rocprofiler_status_t
rocprofiler_thread_trace_decoder_create(rocprofiler_thread_trace_decoder_handle_t* handle,
rocprofiler_thread_trace_decoder_create(rocprofiler_thread_trace_decoder_id_t* handle,
const char* path) ROCPROFILER_API ROCPROFILER_NONNULL(1, 2);
/**
@@ -59,7 +59,7 @@ rocprofiler_thread_trace_decoder_create(rocprofiler_thread_trace_decoder_handle_
* @param[in] handle Handle to destroy
*/
void
rocprofiler_thread_trace_decoder_destroy(rocprofiler_thread_trace_decoder_handle_t handle)
rocprofiler_thread_trace_decoder_destroy(rocprofiler_thread_trace_decoder_id_t handle)
ROCPROFILER_API;
/**
@@ -83,11 +83,11 @@ rocprofiler_thread_trace_decoder_destroy(rocprofiler_thread_trace_decoder_handle
* @retval ::ROCPROFILER_STATUS_SUCCESS Code object loaded
*/
rocprofiler_status_t
rocprofiler_thread_trace_decoder_codeobj_load(rocprofiler_thread_trace_decoder_handle_t handle,
uint64_t load_id,
uint64_t load_addr,
uint64_t load_size,
const void* data,
rocprofiler_thread_trace_decoder_codeobj_load(rocprofiler_thread_trace_decoder_id_t handle,
uint64_t load_id,
uint64_t load_addr,
uint64_t load_size,
const void* data,
uint64_t size) ROCPROFILER_API ROCPROFILER_NONNULL(5);
/**
@@ -100,7 +100,7 @@ rocprofiler_thread_trace_decoder_codeobj_load(rocprofiler_thread_trace_decoder_h
* @retval ::ROCPROFILER_STATUS_SUCCESS Code object unloaded
*/
rocprofiler_status_t
rocprofiler_thread_trace_decoder_codeobj_unload(rocprofiler_thread_trace_decoder_handle_t handle,
rocprofiler_thread_trace_decoder_codeobj_unload(rocprofiler_thread_trace_decoder_id_t handle,
uint64_t load_id) ROCPROFILER_API;
/**
@@ -135,7 +135,7 @@ typedef void (*rocprofiler_thread_trace_decoder_callback_t)(
* @retval ::ROCPROFILER_STATUS_SUCCESS on success
*/
rocprofiler_status_t
rocprofiler_trace_decode(rocprofiler_thread_trace_decoder_handle_t handle,
rocprofiler_trace_decode(rocprofiler_thread_trace_decoder_id_t handle,
rocprofiler_thread_trace_decoder_callback_t callback,
void* data,
uint64_t size,
@@ -148,8 +148,8 @@ rocprofiler_trace_decode(rocprofiler_thread_trace_decoder_handle_t handle,
* @retval null terminated string as description of "info".
*/
const char*
rocprofiler_thread_trace_decoder_info_string(rocprofiler_thread_trace_decoder_handle_t handle,
rocprofiler_thread_trace_decoder_info_t info)
rocprofiler_thread_trace_decoder_info_string(rocprofiler_thread_trace_decoder_id_t handle,
rocprofiler_thread_trace_decoder_info_t info)
ROCPROFILER_API;
/** @} */
+3 -3
ファイルの表示
@@ -41,9 +41,9 @@ namespace rocprofiler
{
namespace att_wrapper
{
ATTFileMgr::ATTFileMgr(Fspath _dir,
std::vector<std::string> _counters,
rocprofiler_thread_trace_decoder_handle_t _decoder)
ATTFileMgr::ATTFileMgr(Fspath _dir,
std::vector<std::string> _counters,
rocprofiler_thread_trace_decoder_id_t _decoder)
: dir(std::move(_dir))
, decoder(_decoder)
{
+5 -5
ファイルの表示
@@ -71,7 +71,7 @@ public:
bool valid() const;
protected:
rocprofiler_thread_trace_decoder_handle_t decoder{};
rocprofiler_thread_trace_decoder_id_t decoder{};
};
class ATTFileMgr
@@ -79,9 +79,9 @@ class ATTFileMgr
using AddressTable = rocprofiler::sdk::codeobj::disassembly::CodeobjAddressTranslate;
public:
ATTFileMgr(Fspath _dir,
std::vector<std::string> _counters,
rocprofiler_thread_trace_decoder_handle_t _decoder);
ATTFileMgr(Fspath _dir,
std::vector<std::string> _counters,
rocprofiler_thread_trace_decoder_id_t _decoder);
~ATTFileMgr();
void addDecoder(const char* filepath, uint64_t id, uint64_t load_addr, uint64_t memsize);
@@ -95,7 +95,7 @@ public:
std::shared_ptr<AddressTable> table{nullptr};
std::map<size_t, std::vector<occupancy_t>> occupancy{};
std::vector<uint64_t> codeobjs_to_delete{};
rocprofiler_thread_trace_decoder_handle_t decoder{};
rocprofiler_thread_trace_decoder_id_t decoder{};
std::array<std::shared_ptr<class WstatesFile>, ROCPROFILER_THREAD_TRACE_DECODER_WSTATE_LAST>
wstates;
+3 -3
ファイルの表示
@@ -103,9 +103,9 @@ get_trace_data(rocprofiler_thread_trace_decoder_record_type_t trace_id,
C_API_END
}
ToolData::ToolData(std::vector<char>& _data,
WaveConfig& _config,
rocprofiler_thread_trace_decoder_handle_t _decoder)
ToolData::ToolData(std::vector<char>& _data,
WaveConfig& _config,
rocprofiler_thread_trace_decoder_id_t _decoder)
: cfile(_config.code)
, config(_config)
, decoder(_decoder)
+4 -4
ファイルの表示
@@ -60,9 +60,9 @@ using SymbolInfo = rocprofiler::sdk::codeobj::disassembly::SymbolInfo;
struct ToolData
{
ToolData(std::vector<char>& data,
WaveConfig& config,
rocprofiler_thread_trace_decoder_handle_t decoder);
ToolData(std::vector<char>& data,
WaveConfig& config,
rocprofiler_thread_trace_decoder_id_t decoder);
~ToolData();
CodeLine& get(pcinfo_t pc);
@@ -73,7 +73,7 @@ struct ToolData
std::vector<char> shader_data{};
size_t num_waves = 0;
rocprofiler_thread_trace_decoder_handle_t decoder{};
rocprofiler_thread_trace_decoder_id_t decoder{};
};
} // namespace att_wrapper
+62 -55
ファイルの表示
@@ -21,6 +21,7 @@
// SOFTWARE.
#include "lib/common/static_object.hpp"
#include "lib/common/synchronized.hpp"
#include "lib/rocprofiler-sdk/aql/helpers.hpp"
#include "lib/rocprofiler-sdk/context/context.hpp"
#include "lib/rocprofiler-sdk/hsa/agent_cache.hpp"
@@ -29,15 +30,19 @@
#include <rocprofiler-sdk/experimental/thread-trace/trace_decoder.h>
#include <rocprofiler-sdk/experimental/thread_trace.h>
#include <rocprofiler-sdk/cxx/hash.hpp>
#include <rocprofiler-sdk/cxx/operators.hpp>
#include <glog/logging.h>
#include <atomic>
#include <cstdint>
namespace
{
using DL = rocprofiler::thread_trace::DL;
using AddressTable = rocprofiler::sdk::codeobj::disassembly::CodeobjAddressTranslate;
using LockedTable = rocprofiler::common::Synchronized<AddressTable>;
class DecoderInstance
{
@@ -46,72 +51,72 @@ public:
: dl(std::move(_dl))
{}
std::unique_ptr<DL> dl{nullptr};
AddressTable table{};
const std::unique_ptr<const DL> dl{nullptr};
LockedTable table{};
};
std::mutex map_mut;
using DecoderMap =
std::unordered_map<rocprofiler_thread_trace_decoder_id_t, std::shared_ptr<DecoderInstance>>;
using LockedMap = rocprofiler::common::Synchronized<DecoderMap>;
auto&
get_dlopens()
get_dlmap()
{
static auto*& _v = rocprofiler::common::static_object<
std::unordered_map<uint64_t, std::shared_ptr<DecoderInstance>>>::construct();
static auto*& _v = rocprofiler::common::static_object<LockedMap>::construct();
return *CHECK_NOTNULL(_v);
}
std::shared_ptr<DecoderInstance>
get_dl(rocprofiler_thread_trace_decoder_handle_t handle)
get_dl(rocprofiler_thread_trace_decoder_id_t handle)
{
auto lk = std::unique_lock{map_mut};
auto it = get_dlopens().find(handle.handle);
if(it == get_dlopens().end()) return nullptr;
return it->second;
return get_dlmap().rlock([&](const DecoderMap& map) -> std::shared_ptr<DecoderInstance> {
if(auto it = map.find(handle); it != map.end()) return it->second;
return nullptr;
});
}
} // namespace
extern "C" {
rocprofiler_status_t
rocprofiler_thread_trace_decoder_create(rocprofiler_thread_trace_decoder_handle_t* handle,
const char* path)
rocprofiler_thread_trace_decoder_create(rocprofiler_thread_trace_decoder_id_t* handle,
const char* path)
{
auto dl = std::make_unique<DL>(path);
if(dl->handle == nullptr) return ROCPROFILER_STATUS_ERROR_NOT_AVAILABLE;
if(!dl->valid()) return ROCPROFILER_STATUS_ERROR_INCOMPATIBLE_ABI;
auto lk = std::unique_lock{map_mut};
static uint64_t count = 1;
static std::atomic<uint64_t> count{1};
handle->handle = count.fetch_add(1);
auto instance = std::make_shared<DecoderInstance>(std::move(dl));
handle->handle = count++;
get_dlopens()[handle->handle] = std::move(instance);
get_dlmap().wlock(
[&](DecoderMap& map) { map[*handle] = std::make_shared<DecoderInstance>(std::move(dl)); });
return ROCPROFILER_STATUS_SUCCESS;
}
void
rocprofiler_thread_trace_decoder_destroy(rocprofiler_thread_trace_decoder_handle_t handle)
rocprofiler_thread_trace_decoder_destroy(rocprofiler_thread_trace_decoder_id_t handle)
{
auto lk = std::unique_lock{map_mut};
get_dlopens().erase(handle.handle);
get_dlmap().wlock([&](DecoderMap& map) { map.erase(handle); });
}
rocprofiler_status_t
rocprofiler_thread_trace_decoder_codeobj_load(rocprofiler_thread_trace_decoder_handle_t handle,
uint64_t load_id,
uint64_t load_addr,
uint64_t load_size,
const void* data,
uint64_t size)
rocprofiler_thread_trace_decoder_codeobj_load(rocprofiler_thread_trace_decoder_id_t handle,
uint64_t load_id,
uint64_t load_addr,
uint64_t load_size,
const void* data,
uint64_t size)
{
auto decoder = get_dl(handle);
if(decoder == nullptr) return ROCPROFILER_STATUS_ERROR_INVALID_ARGUMENT;
try
{
decoder->table.addDecoder(data, size, load_id, load_addr, load_size);
decoder->table.wlock([&](AddressTable& table) {
table.addDecoder(data, size, load_id, load_addr, load_size);
});
} catch(...)
{
return ROCPROFILER_STATUS_ERROR;
@@ -120,15 +125,17 @@ rocprofiler_thread_trace_decoder_codeobj_load(rocprofiler_thread_trace_decoder_h
}
rocprofiler_status_t
rocprofiler_thread_trace_decoder_codeobj_unload(rocprofiler_thread_trace_decoder_handle_t handle,
uint64_t load_id)
rocprofiler_thread_trace_decoder_codeobj_unload(rocprofiler_thread_trace_decoder_id_t handle,
uint64_t load_id)
{
auto decoder = get_dl(handle);
if(decoder == nullptr) return ROCPROFILER_STATUS_ERROR_INVALID_ARGUMENT;
try
{
if(decoder->table.removeDecoder(load_id)) return ROCPROFILER_STATUS_SUCCESS;
bool result =
decoder->table.wlock([&](AddressTable& table) { return table.removeDecoder(load_id); });
if(result) return ROCPROFILER_STATUS_SUCCESS;
} catch(std::exception&)
{}
@@ -169,32 +176,32 @@ isa_callback(char* isa_instruction,
void* userdata)
{
ROCP_FATAL_IF(userdata == nullptr) << "Userdata is null!";
auto& table = static_cast<trace_data_t*>(userdata)->decoder->table;
std::unique_ptr<Instruction> instruction{nullptr};
auto decoder = static_cast<trace_data_t*>(userdata)->decoder;
ROCP_FATAL_IF(decoder == nullptr) << "decoder is null";
try
{
instruction = table.get(pc.marker_id, pc.addr);
auto instruction = decoder->table.wlock(
[&](AddressTable& table) { return table.get(pc.marker_id, pc.addr); });
if(!instruction) return ROCPROFILER_THREAD_TRACE_DECODER_STATUS_ERROR_INVALID_ARGUMENT;
{
size_t tmp_isa_size = *isa_size;
*isa_size = instruction->inst.size();
if(*isa_size > tmp_isa_size)
return ROCPROFILER_THREAD_TRACE_DECODER_STATUS_ERROR_OUT_OF_RESOURCES;
}
memcpy(isa_instruction, instruction->inst.data(), *isa_size);
*isa_memory_size = instruction->size;
} catch(std::exception& e)
{
ROCP_WARNING << pc.marker_id << ":" << pc.addr << ' ' << e.what();
ROCP_CI_LOG(INFO) << pc.marker_id << ":" << pc.addr << ' ' << e.what();
return ROCPROFILER_THREAD_TRACE_DECODER_STATUS_ERROR;
}
if(!instruction) return ROCPROFILER_THREAD_TRACE_DECODER_STATUS_ERROR_INVALID_ARGUMENT;
{
size_t tmp_isa_size = *isa_size;
*isa_size = instruction->inst.size();
if(*isa_size > tmp_isa_size)
return ROCPROFILER_THREAD_TRACE_DECODER_STATUS_ERROR_OUT_OF_RESOURCES;
}
memcpy(isa_instruction, instruction->inst.data(), *isa_size);
*isa_memory_size = instruction->size;
return ROCPROFILER_THREAD_TRACE_DECODER_STATUS_SUCCESS;
}
@@ -214,7 +221,7 @@ trace_callback(rocprofiler_thread_trace_decoder_record_type_t record_type_id,
extern "C" {
rocprofiler_status_t
rocprofiler_trace_decode(rocprofiler_thread_trace_decoder_handle_t handle,
rocprofiler_trace_decode(rocprofiler_thread_trace_decoder_id_t handle,
rocprofiler_thread_trace_decoder_callback_t user_callback,
void* data,
uint64_t size,
@@ -249,8 +256,8 @@ rocprofiler_trace_decode(rocprofiler_thread_trace_decoder_handle_t handle,
}
const char*
rocprofiler_thread_trace_decoder_info_string(rocprofiler_thread_trace_decoder_handle_t handle,
rocprofiler_thread_trace_decoder_info_t info)
rocprofiler_thread_trace_decoder_info_string(rocprofiler_thread_trace_decoder_id_t handle,
rocprofiler_thread_trace_decoder_info_t info)
{
auto decoder = get_dl(handle);
if(decoder == nullptr) return nullptr;