b60c0ceddd
* Remove config checks for stream and kernel rename data collection * Updated csv generation to check if kernel rename is on before calling get_kernel_name * Update metadata to use kernel_rename bool argument * Formatting + unconditionally store kernel name in rocpd * Readded kernel rename parameter after rebase * Fixed rebase conflicts * Updated comment in line with github comments * Added check in rocpd csv.cpp to output kernel name if region name is empty * Add test for kernel rename --------- Co-authored-by: Ian Trowbridge <Ian.Trowbridge@amd.com>
874 γραμμές
28 KiB
C++
874 γραμμές
28 KiB
C++
// MIT License
|
|
//
|
|
// Copyright (c) 2023-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 "metadata.hpp"
|
|
#include "agent_info.hpp"
|
|
#include "host_symbol_info.hpp"
|
|
#include "kernel_symbol_info.hpp"
|
|
#include "node_info.hpp"
|
|
|
|
#include "lib/att-tool/att_lib_wrapper.hpp"
|
|
#include "lib/common/environment.hpp"
|
|
#include "lib/common/filesystem.hpp"
|
|
#include "lib/common/logging.hpp"
|
|
#include "lib/common/string_entry.hpp"
|
|
#include "lib/common/utility.hpp"
|
|
#include "lib/output/agent_info.hpp"
|
|
#include "lib/output/host_symbol_info.hpp"
|
|
#include "lib/output/kernel_symbol_info.hpp"
|
|
#include "lib/output/node_info.hpp"
|
|
|
|
#include <rocprofiler-sdk/fwd.h>
|
|
#include <rocprofiler-sdk/rocprofiler.h>
|
|
#include <rocprofiler-sdk/cxx/details/tokenize.hpp>
|
|
|
|
#include <fmt/core.h>
|
|
#include <fmt/format.h>
|
|
|
|
#include <dlfcn.h>
|
|
#include <unistd.h>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace rocprofiler
|
|
{
|
|
namespace tool
|
|
{
|
|
namespace
|
|
{
|
|
namespace fs = ::rocprofiler::common::filesystem;
|
|
|
|
rocprofiler_status_t
|
|
query_pc_sampling_configuration(const rocprofiler_pc_sampling_configuration_t* configs,
|
|
long unsigned int num_config,
|
|
void* user_data)
|
|
{
|
|
auto* avail_configs =
|
|
static_cast<std::vector<rocprofiler_pc_sampling_configuration_t>*>(user_data);
|
|
for(size_t i = 0; i < num_config; i++)
|
|
{
|
|
avail_configs->emplace_back(configs[i]);
|
|
}
|
|
return ROCPROFILER_STATUS_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief Processes and stores the supported counters for a given agent.
|
|
*
|
|
* This function iterates over all counters supported by the given agent.
|
|
* If a filter set is provided, only counters present in the filter set are processed.
|
|
* Otherwise, all counters are collected.
|
|
*
|
|
* @param agent_id The ID of the agent whose counters are being processed.
|
|
* @param filter_set Optional set of counter names to filter which counters to load. If null,
|
|
* all supported counters will be loaded.
|
|
* @param output_map A reference to the map where the processed counter information will be stored.
|
|
*
|
|
* @return ROCPROFILER_STATUS_SUCCESS on success, or an appropriate error status on failure.
|
|
*/
|
|
rocprofiler_status_t
|
|
process_agent_counters(rocprofiler_agent_id_t agent_id,
|
|
std::set<std::string>* filter_set,
|
|
agent_counter_info_map_t& output_map)
|
|
{
|
|
struct callback_data_t
|
|
{
|
|
std::set<std::string>* counters_set = nullptr;
|
|
agent_counter_info_map_t* agent_counter_info = nullptr;
|
|
};
|
|
|
|
auto cb_data = callback_data_t{filter_set, &output_map};
|
|
|
|
return rocprofiler_iterate_agent_supported_counters(
|
|
agent_id,
|
|
[](rocprofiler_agent_id_t id,
|
|
rocprofiler_counter_id_t* counters,
|
|
size_t num_counters,
|
|
void* user_data) {
|
|
auto* data = static_cast<callback_data_t*>(user_data);
|
|
auto* counters_set_data = data->counters_set;
|
|
auto* agent_counter_info_data = data->agent_counter_info;
|
|
|
|
agent_counter_info_data->emplace(id, counter_info_vec_t{});
|
|
|
|
for(size_t i = 0; i < num_counters; ++i)
|
|
{
|
|
auto _info = rocprofiler_counter_info_v1_t{};
|
|
auto _dim_ids = std::vector<rocprofiler_counter_dimension_id_t>{};
|
|
auto _dim_info = std::vector<rocprofiler_counter_record_dimension_info_t>{};
|
|
|
|
ROCPROFILER_CHECK(rocprofiler_query_counter_info(
|
|
counters[i], ROCPROFILER_COUNTER_INFO_VERSION_1, &_info));
|
|
|
|
if(counters_set_data != nullptr && counters_set_data->count(_info.name) == 0)
|
|
continue;
|
|
|
|
for(uint64_t j = 0; j < _info.dimensions_count; ++j)
|
|
{
|
|
if(_info.dimensions[j] == nullptr)
|
|
{
|
|
ROCP_WARNING << fmt::format(
|
|
"nullptr dimension encountered for counter '{}' at index {}",
|
|
_info.name,
|
|
j);
|
|
continue;
|
|
}
|
|
|
|
_dim_ids.emplace_back(_info.dimensions[j]->id);
|
|
_dim_info.emplace_back(*_info.dimensions[j]);
|
|
}
|
|
|
|
agent_counter_info_data->at(id).emplace_back(
|
|
id, _info, std::move(_dim_ids), std::move(_dim_info));
|
|
}
|
|
|
|
return ROCPROFILER_STATUS_SUCCESS;
|
|
},
|
|
&cb_data);
|
|
}
|
|
} // namespace
|
|
|
|
kernel_symbol_info::kernel_symbol_info()
|
|
: base_type{0, 0, 0, "", 0, 0, 0, 0, 0, 0, 0, 0, 0, {.handle = 0}}
|
|
{}
|
|
|
|
constexpr auto null_address_v = rocprofiler_address_t{.handle = 0};
|
|
constexpr auto null_dim3_v = rocprofiler_dim3_t{.x = 0, .y = 0, .z = 0};
|
|
|
|
host_function_info::host_function_info()
|
|
: base_type{0,
|
|
0,
|
|
0,
|
|
0,
|
|
null_address_v,
|
|
null_address_v,
|
|
"",
|
|
0,
|
|
null_dim3_v,
|
|
null_dim3_v,
|
|
null_dim3_v,
|
|
null_dim3_v,
|
|
0}
|
|
{}
|
|
|
|
metadata::metadata(inprocess)
|
|
: buffer_names{sdk::get_buffer_tracing_names()}
|
|
, callback_names{sdk::get_callback_tracing_names()}
|
|
, node_data{read_node_info()}
|
|
, command_line{common::read_command_line(getpid())}
|
|
{
|
|
ROCPROFILER_CHECK(rocprofiler_query_available_agents(
|
|
ROCPROFILER_AGENT_INFO_VERSION_0,
|
|
[](rocprofiler_agent_version_t, const void** _agents, size_t _num_agents, void* _data) {
|
|
auto* _agents_v = static_cast<agent_info_vec_t*>(_data);
|
|
_agents_v->reserve(_num_agents);
|
|
for(size_t i = 0; i < _num_agents; ++i)
|
|
{
|
|
auto* agent = static_cast<const rocprofiler_agent_v0_t*>(_agents[i]);
|
|
_agents_v->emplace_back(*agent);
|
|
}
|
|
return ROCPROFILER_STATUS_SUCCESS;
|
|
},
|
|
sizeof(rocprofiler_agent_v0_t),
|
|
&agents));
|
|
|
|
{
|
|
auto _gpu_agents = std::vector<agent_info*>{};
|
|
|
|
_gpu_agents.reserve(agents.size());
|
|
for(auto& itr : agents)
|
|
{
|
|
if(itr.type == ROCPROFILER_AGENT_TYPE_GPU)
|
|
{
|
|
_gpu_agents.emplace_back(&itr);
|
|
auto pc_configs = std::vector<rocprofiler_pc_sampling_configuration_t>{};
|
|
rocprofiler_query_pc_sampling_agent_configurations(
|
|
itr.id, query_pc_sampling_configuration, &pc_configs);
|
|
agent_pc_sample_config_info.emplace(itr.id, pc_configs);
|
|
}
|
|
}
|
|
|
|
// make sure they are sorted by node id
|
|
std::sort(_gpu_agents.begin(), _gpu_agents.end(), [](const auto& lhs, const auto& rhs) {
|
|
return CHECK_NOTNULL(lhs)->node_id < CHECK_NOTNULL(rhs)->node_id;
|
|
});
|
|
|
|
int64_t _dev_id = 0;
|
|
for(auto& itr : _gpu_agents)
|
|
itr->gpu_index = _dev_id++;
|
|
}
|
|
|
|
for(auto itr : agents)
|
|
agents_map.emplace(itr.id, itr);
|
|
|
|
// Add kernel ID of zero
|
|
kernel_symbol_info info{};
|
|
info.kernel_id = 0;
|
|
info.formatted_kernel_name = "0";
|
|
info.demangled_kernel_name = "0";
|
|
info.truncated_kernel_name = "0";
|
|
add_kernel_symbol(std::move(info));
|
|
}
|
|
|
|
/**
|
|
* @brief Initializes the metadata by loading all counters supported on GPU agents.
|
|
*
|
|
* This method is used by the `rocprofv3-avail` tool to enumerate all available counters
|
|
* for each GPU agent in the system.
|
|
*
|
|
* For each non-CPU agent, this function calls `process_agent_counters` with a null filter,
|
|
* ensuring that all counters supported by that agent are queried and stored in metadata.
|
|
*/
|
|
void metadata::init(inprocess)
|
|
{
|
|
if(inprocess_init) return;
|
|
inprocess_init = true;
|
|
|
|
for(const auto& agent : agents)
|
|
{
|
|
if(agent.type == ROCPROFILER_AGENT_TYPE_CPU) continue;
|
|
|
|
auto status = process_agent_counters(agent.id, nullptr, agent_counter_info);
|
|
ROCP_WARNING_IF(status != ROCPROFILER_STATUS_SUCCESS) << fmt::format(
|
|
"rocprofiler_iterate_agent_supported_counters failed for agent {} ({}) :: {}",
|
|
agent.node_id,
|
|
agent.name,
|
|
rocprofiler_get_status_string(status));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Initializes the metadata by loading only selected counters for GPU agents.
|
|
*
|
|
* This method is used by the `rocprofv3` tool when profiling with a list
|
|
* of performance counters which are profiled by user.
|
|
*
|
|
* This filtering reduces runtime overhead and significantly shrinks the size of
|
|
* generated JSON metadata in profiling output.
|
|
*/
|
|
void
|
|
metadata::init(inprocess_with_counters&& data)
|
|
{
|
|
if(inprocess_init) return;
|
|
inprocess_init = true;
|
|
|
|
// No counters to process, exit early. Kernel trace doesn't have to iterate counters.
|
|
if(data.counters.empty()) return;
|
|
|
|
auto gpu_index_to_counters_map = std::map<int, std::set<std::string>>{};
|
|
for(const auto& agent : agents)
|
|
{
|
|
gpu_index_to_counters_map[agent.gpu_index] = {};
|
|
}
|
|
|
|
// Used to parse counters like "SQ_WAVES:device=0".
|
|
constexpr auto device_qualifier = std::string_view{":device="};
|
|
|
|
for(const auto& pmc_counter : data.counters)
|
|
{
|
|
auto name_v = pmc_counter;
|
|
|
|
if(auto pos = pmc_counter.find(device_qualifier); pos != std::string::npos)
|
|
{
|
|
name_v = pmc_counter.substr(0, pos);
|
|
auto device_id_s = pmc_counter.substr(pos + device_qualifier.length());
|
|
|
|
ROCP_FATAL_IF(device_id_s.empty() ||
|
|
device_id_s.find_first_not_of("0123456789") != std::string::npos)
|
|
<< fmt::format("Invalid device qualifier format (expected ':device=N') in '{}'",
|
|
pmc_counter);
|
|
|
|
auto device_id_l = std::stol(device_id_s);
|
|
if(gpu_index_to_counters_map.find(device_id_l) == gpu_index_to_counters_map.end())
|
|
{
|
|
ROCP_WARNING << fmt::format("Device ID not found for PMC counter '{}'",
|
|
pmc_counter);
|
|
continue;
|
|
}
|
|
|
|
// Add the counter to the corresponding device.
|
|
gpu_index_to_counters_map[device_id_l].emplace(name_v);
|
|
}
|
|
else
|
|
{
|
|
// No device qualifier — add to all devices.
|
|
for(auto& [_, counters] : gpu_index_to_counters_map)
|
|
counters.emplace(name_v);
|
|
}
|
|
}
|
|
|
|
// Process selected counters for each GPU agent.
|
|
for(const auto& agent : agents)
|
|
{
|
|
if(agent.type == ROCPROFILER_AGENT_TYPE_CPU) continue;
|
|
|
|
auto* filter = &gpu_index_to_counters_map[agent.gpu_index];
|
|
auto status = process_agent_counters(agent.id, filter, agent_counter_info);
|
|
|
|
ROCP_WARNING_IF(status != ROCPROFILER_STATUS_SUCCESS) << fmt::format(
|
|
"rocprofiler_iterate_agent_supported_counters failed for agent {} ({}) :: {}",
|
|
agent.node_id,
|
|
agent.name,
|
|
rocprofiler_get_status_string(status));
|
|
}
|
|
}
|
|
|
|
const agent_info*
|
|
metadata::get_agent(rocprofiler_agent_id_t _val) const
|
|
{
|
|
for(const auto& itr : agents)
|
|
{
|
|
if(itr.id == _val) return &itr;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
const code_object_info*
|
|
metadata::get_code_object(uint64_t code_obj_id) const
|
|
{
|
|
return code_objects.rlock([code_obj_id](const auto& _data) -> const code_object_info* {
|
|
return &_data.at(code_obj_id);
|
|
});
|
|
}
|
|
|
|
code_object_load_info_vec_t
|
|
metadata::get_code_object_load_info() const
|
|
{
|
|
auto _data = code_object_load.rlock([](const auto& _data_v) {
|
|
auto _info = std::vector<rocprofiler::att_wrapper::CodeobjLoadInfo>{};
|
|
_info.reserve(_data_v.size());
|
|
for(const auto& itr : _data_v)
|
|
_info.emplace_back(itr);
|
|
return _info;
|
|
});
|
|
|
|
uint64_t _sz = 0;
|
|
for(const auto& itr : _data)
|
|
_sz = std::max(_sz, itr.id);
|
|
|
|
ROCP_WARNING_IF((_sz + 1) - _data.size() > 1000) << fmt::format(
|
|
"Spares index detected for code object load info: {} < {}", _data.size(), _sz);
|
|
|
|
auto _code_obj_data = std::vector<rocprofiler::att_wrapper::CodeobjLoadInfo>{};
|
|
_code_obj_data.resize(_sz + 1, rocprofiler::att_wrapper::CodeobjLoadInfo{});
|
|
// index by the code object id
|
|
for(auto& itr : _data)
|
|
_code_obj_data.at(itr.id) = itr;
|
|
|
|
return _code_obj_data;
|
|
}
|
|
|
|
std::vector<std::string>
|
|
metadata::get_att_filenames() const
|
|
{
|
|
auto data = std::vector<std::string>{};
|
|
for(const auto& filenames : att_filenames)
|
|
{
|
|
for(const auto& file : filenames.second.second)
|
|
{
|
|
data.emplace_back(fs::path{file}.filename());
|
|
}
|
|
}
|
|
return data;
|
|
}
|
|
|
|
const kernel_symbol_info*
|
|
metadata::get_kernel_symbol(uint64_t kernel_id) const
|
|
{
|
|
return kernel_symbols.rlock([kernel_id](const auto& _data) -> const kernel_symbol_info* {
|
|
return &_data.at(kernel_id);
|
|
});
|
|
}
|
|
|
|
const host_function_info*
|
|
metadata::get_host_function(uint64_t host_function_id) const
|
|
{
|
|
return host_functions.rlock([host_function_id](const auto& _data) -> const host_function_info* {
|
|
return &_data.at(host_function_id);
|
|
});
|
|
}
|
|
|
|
const tool_counter_info*
|
|
metadata::get_counter_info(uint64_t instance_id) const
|
|
{
|
|
auto _counter_id = rocprofiler_counter_id_t{.handle = 0};
|
|
ROCPROFILER_CHECK(rocprofiler_query_record_counter_id(instance_id, &_counter_id));
|
|
return get_counter_info(_counter_id);
|
|
}
|
|
|
|
const tool_counter_info*
|
|
metadata::get_counter_info(rocprofiler_counter_id_t id) const
|
|
{
|
|
for(const auto& itr : agent_counter_info)
|
|
{
|
|
for(const auto& aitr : itr.second)
|
|
{
|
|
if(aitr.id == id) return &aitr;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
const counter_dimension_info_vec_t*
|
|
metadata::get_counter_dimension_info(uint64_t instance_id) const
|
|
{
|
|
return &CHECK_NOTNULL(get_counter_info(instance_id))->dimensions;
|
|
}
|
|
|
|
code_object_data_vec_t
|
|
metadata::get_code_objects() const
|
|
{
|
|
auto _data = code_objects.rlock([](const auto& _data_v) {
|
|
auto _info = std::vector<code_object_info>{};
|
|
_info.reserve(_data_v.size());
|
|
for(const auto& itr : _data_v)
|
|
_info.emplace_back(itr.second);
|
|
return _info;
|
|
});
|
|
|
|
uint64_t _sz = 0;
|
|
for(const auto& itr : _data)
|
|
_sz = std::max(_sz, itr.code_object_id);
|
|
|
|
auto _code_obj_data = std::vector<code_object_info>{};
|
|
_code_obj_data.resize(_sz + 1, code_object_info{});
|
|
// index by the code object id
|
|
for(auto& itr : _data)
|
|
_code_obj_data.at(itr.code_object_id) = itr;
|
|
|
|
return _code_obj_data;
|
|
}
|
|
|
|
kernel_symbol_data_vec_t
|
|
metadata::get_kernel_symbols() const
|
|
{
|
|
auto _data = kernel_symbols.rlock([](const auto& _data_v) {
|
|
auto _info = std::vector<kernel_symbol_info>{};
|
|
_info.reserve(_data_v.size());
|
|
for(const auto& itr : _data_v)
|
|
_info.emplace_back(itr.second);
|
|
return _info;
|
|
});
|
|
|
|
uint64_t kernel_data_size = 0;
|
|
for(const auto& itr : _data)
|
|
kernel_data_size = std::max(kernel_data_size, itr.kernel_id);
|
|
|
|
auto _symbol_data = std::vector<kernel_symbol_info>{};
|
|
_symbol_data.resize(kernel_data_size + 1, kernel_symbol_info{});
|
|
// index by the kernel id
|
|
for(auto& itr : _data)
|
|
_symbol_data.at(itr.kernel_id) = std::move(itr);
|
|
|
|
return _symbol_data;
|
|
}
|
|
|
|
host_function_data_vec_t
|
|
metadata::get_host_symbols() const
|
|
{
|
|
return host_functions.rlock([](const auto& _data_v) {
|
|
auto _info = std::vector<host_function_info>{};
|
|
_info.resize(_data_v.size() + 1, host_function_info{});
|
|
for(const auto& itr : _data_v)
|
|
_info.at(itr.first) = itr.second;
|
|
return _info;
|
|
});
|
|
}
|
|
|
|
metadata::agent_info_ptr_vec_t
|
|
metadata::get_gpu_agents() const
|
|
{
|
|
auto _data = metadata::agent_info_ptr_vec_t{};
|
|
for(const auto& itr : agents)
|
|
{
|
|
if(itr.type == ROCPROFILER_AGENT_TYPE_GPU) _data.emplace_back(&itr);
|
|
}
|
|
return _data;
|
|
}
|
|
|
|
pc_sample_config_vec_t
|
|
metadata::get_pc_sample_config_info(rocprofiler_agent_id_t _val) const
|
|
{
|
|
auto _ret = pc_sample_config_vec_t{};
|
|
if(agent_pc_sample_config_info.find(_val) == agent_pc_sample_config_info.end()) return _ret;
|
|
auto pc_sample_config = agent_pc_sample_config_info.at(_val);
|
|
for(const auto& itr : pc_sample_config)
|
|
{
|
|
_ret.emplace_back(itr);
|
|
}
|
|
return _ret;
|
|
}
|
|
|
|
counter_info_vec_t
|
|
metadata::get_counter_info() const
|
|
{
|
|
auto _ret = std::vector<tool_counter_info>{};
|
|
for(const auto& itr : agent_counter_info)
|
|
{
|
|
for(const auto& iitr : itr.second)
|
|
_ret.emplace_back(iitr);
|
|
}
|
|
return _ret;
|
|
}
|
|
|
|
counter_dimension_vec_t
|
|
metadata::get_counter_dimension_info() const
|
|
{
|
|
auto _ret = counter_dimension_vec_t{};
|
|
for(const auto& itr : agent_counter_info)
|
|
{
|
|
for(const auto& iitr : itr.second)
|
|
for(const auto& ditr : iitr.dimensions)
|
|
_ret.emplace_back(ditr);
|
|
}
|
|
|
|
auto _sorter = [](const rocprofiler_counter_record_dimension_info_t& lhs,
|
|
const rocprofiler_counter_record_dimension_info_t& rhs) {
|
|
return std::tie(lhs.id, lhs.instance_size) < std::tie(rhs.id, rhs.instance_size);
|
|
};
|
|
auto _equiv = [](const rocprofiler_counter_record_dimension_info_t& lhs,
|
|
const rocprofiler_counter_record_dimension_info_t& rhs) {
|
|
return std::tie(lhs.id, lhs.instance_size) == std::tie(rhs.id, rhs.instance_size);
|
|
};
|
|
|
|
std::sort(_ret.begin(), _ret.end(), _sorter);
|
|
_ret.erase(std::unique(_ret.begin(), _ret.end(), _equiv), _ret.end());
|
|
|
|
return _ret;
|
|
}
|
|
|
|
metadata::string_index_map_t
|
|
metadata::get_string_entries() const
|
|
{
|
|
return string_entries.rlock([](const auto& _inp) {
|
|
auto _sorted = std::vector<std::string_view>{};
|
|
_sorted.reserve(_inp.size());
|
|
for(const auto& itr : _inp)
|
|
_sorted.emplace_back(std::string_view{*itr.second});
|
|
std::sort(_sorted.begin(), _sorted.end());
|
|
|
|
auto _ret = string_index_map_t{};
|
|
size_t _idx = 1;
|
|
for(const auto& itr : _sorted)
|
|
_ret.emplace(itr, _idx++);
|
|
|
|
return _ret;
|
|
});
|
|
}
|
|
|
|
bool
|
|
metadata::add_marker_message(uint64_t corr_id, std::string&& msg)
|
|
{
|
|
return marker_messages.wlock(
|
|
[](auto& _data, uint64_t _cid_v, std::string&& _msg) -> bool {
|
|
return _data.emplace(_cid_v, std::move(_msg)).second;
|
|
},
|
|
corr_id,
|
|
std::move(msg));
|
|
}
|
|
|
|
bool
|
|
metadata::add_code_object(code_object_info obj)
|
|
{
|
|
return code_objects.wlock(
|
|
[](code_object_data_map_t& _data_v, code_object_info _obj_v) -> bool {
|
|
return _data_v.emplace(_obj_v.code_object_id, _obj_v).second;
|
|
},
|
|
obj);
|
|
}
|
|
|
|
bool
|
|
metadata::add_kernel_symbol(kernel_symbol_info&& sym)
|
|
{
|
|
return kernel_symbols.wlock(
|
|
[](kernel_symbol_data_map_t& _data_v, kernel_symbol_info&& _sym_v) -> bool {
|
|
return _data_v.emplace(_sym_v.kernel_id, std::move(_sym_v)).second;
|
|
},
|
|
std::move(sym));
|
|
}
|
|
|
|
bool
|
|
metadata::add_host_function(host_function_info&& func)
|
|
{
|
|
return host_functions.wlock(
|
|
[](host_function_info_map_t& _data_v, host_function_info&& _func_v) -> bool {
|
|
return _data_v.emplace(_func_v.host_function_id, std::move(_func_v)).second;
|
|
},
|
|
std::move(func));
|
|
}
|
|
|
|
bool
|
|
metadata::add_string_entry(size_t key, std::string_view str)
|
|
{
|
|
return string_entries.ulock(
|
|
[](const auto& _data, size_t _key, std::string_view) { return (_data.count(_key) > 0); },
|
|
[](auto& _data, size_t _key, std::string_view _str) {
|
|
_data.emplace(_key, new std::string{_str});
|
|
return true;
|
|
},
|
|
key,
|
|
str);
|
|
}
|
|
|
|
bool
|
|
metadata::add_external_correlation_id(uint64_t val)
|
|
{
|
|
return external_corr_ids.wlock(
|
|
[](auto& _data, uint64_t _val) { return _data.emplace(_val).second; }, val);
|
|
}
|
|
|
|
bool
|
|
metadata::add_runtime_initialization(rocprofiler_runtime_initialization_operation_t runtime_op)
|
|
{
|
|
return runtime_initialization_set.wlock(
|
|
[](auto& _data, rocprofiler_runtime_initialization_operation_t _runtime_op) {
|
|
return _data.emplace(_runtime_op).second;
|
|
},
|
|
runtime_op);
|
|
}
|
|
|
|
uint64_t
|
|
metadata::add_kernel_rename_val(std::string_view rename_string, uint64_t internal_corr_id)
|
|
{
|
|
return kernel_rename_map.wlock(
|
|
[](auto& _data, std::string_view _str, uint64_t _val) {
|
|
return _data.emplace(_str, _val).first->second;
|
|
},
|
|
rename_string,
|
|
internal_corr_id);
|
|
}
|
|
|
|
bool
|
|
metadata::is_runtime_initialized(rocprofiler_runtime_initialization_operation_t runtime_op) const
|
|
{
|
|
return runtime_initialization_set.rlock(
|
|
[](const auto& _data, rocprofiler_runtime_initialization_operation_t _runtime_op) {
|
|
return _data.count(_runtime_op) > 0;
|
|
},
|
|
runtime_op);
|
|
}
|
|
|
|
void
|
|
metadata::set_process_id(pid_t _pid, pid_t _ppid, const std::vector<std::string>& _command_line)
|
|
{
|
|
process_id = _pid;
|
|
parent_process_id = _ppid;
|
|
|
|
if(!_command_line.empty())
|
|
command_line = _command_line;
|
|
else if(_pid == getpid())
|
|
command_line = common::read_command_line(_pid);
|
|
|
|
if(auto _start_ns = common::get_process_start_time_ns(_pid); _start_ns > 0)
|
|
process_start_ns = _start_ns;
|
|
}
|
|
|
|
std::string_view
|
|
metadata::get_marker_message(uint64_t corr_id) const
|
|
{
|
|
return marker_messages.rlock(
|
|
[](const auto& _data, uint64_t _corr_id_v) -> std::string_view {
|
|
return (_data.count(_corr_id_v) > 0) ? _data.at(_corr_id_v) : std::string_view{};
|
|
},
|
|
corr_id);
|
|
}
|
|
|
|
std::string_view
|
|
metadata::get_kernel_name(uint64_t kernel_id, bool rename_kernel, uint64_t rename_id) const
|
|
{
|
|
if(rename_kernel)
|
|
{
|
|
auto string_entry = kernel_rename_map.rlock(
|
|
[](auto& _data, uint64_t _val) {
|
|
for(const auto& itr : _data)
|
|
if(itr.second == _val) return itr.first;
|
|
return std::string_view{};
|
|
},
|
|
rename_id);
|
|
if(!string_entry.empty())
|
|
{
|
|
if(const auto* _name = common::get_string_entry(string_entry))
|
|
return std::string_view{*_name};
|
|
}
|
|
}
|
|
|
|
const auto* _kernel_data = get_kernel_symbol(kernel_id);
|
|
return CHECK_NOTNULL(_kernel_data)->formatted_kernel_name;
|
|
}
|
|
|
|
std::string_view
|
|
metadata::get_kind_name(rocprofiler_callback_tracing_kind_t kind) const
|
|
{
|
|
return callback_names.at(kind);
|
|
}
|
|
|
|
std::string_view
|
|
metadata::get_kind_name(rocprofiler_buffer_tracing_kind_t kind) const
|
|
{
|
|
return buffer_names.at(kind);
|
|
}
|
|
|
|
std::string_view
|
|
metadata::get_operation_name(rocprofiler_callback_tracing_kind_t kind,
|
|
rocprofiler_tracing_operation_t op) const
|
|
{
|
|
return callback_names.at(kind, op);
|
|
}
|
|
|
|
std::string_view
|
|
metadata::get_operation_name(rocprofiler_buffer_tracing_kind_t kind,
|
|
rocprofiler_tracing_operation_t op) const
|
|
{
|
|
return buffer_names.at(kind, op);
|
|
}
|
|
|
|
agent_index
|
|
metadata::get_agent_index(rocprofiler_agent_id_t id, agent_indexing index) const
|
|
{
|
|
const auto* _agent = get_agent(id);
|
|
ROCP_FATAL_IF(!_agent) << "Information of the agent with handle: " << id.handle
|
|
<< " is not present";
|
|
|
|
// stringify agent type
|
|
auto get_type = [_agent]() -> std::string_view {
|
|
switch(_agent->type)
|
|
{
|
|
case ROCPROFILER_AGENT_TYPE_CPU: return "CPU";
|
|
case ROCPROFILER_AGENT_TYPE_GPU: return "GPU";
|
|
case ROCPROFILER_AGENT_TYPE_NONE:
|
|
case ROCPROFILER_AGENT_TYPE_LAST: break;
|
|
}
|
|
return "UNK";
|
|
};
|
|
|
|
return create_agent_index(
|
|
index,
|
|
_agent->node_id, // absolute index
|
|
static_cast<uint32_t>(_agent->logical_node_id), // relative index
|
|
static_cast<uint32_t>(_agent->logical_node_type_id), // type-relative index
|
|
get_type());
|
|
}
|
|
|
|
const std::string*
|
|
metadata::get_string_entry(size_t key) const
|
|
{
|
|
const auto* ret = string_entries.rlock(
|
|
[](const auto& _data, size_t _key) -> const std::string* {
|
|
if(_data.count(_key) > 0) return _data.at(_key).get();
|
|
return nullptr;
|
|
},
|
|
key);
|
|
|
|
if(!ret) ret = common::get_string_entry(key);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int64_t
|
|
metadata::get_instruction_index(rocprofiler_pc_t record)
|
|
{
|
|
inst_t ins;
|
|
ins.code_object_id = record.code_object_id;
|
|
ins.code_object_offset = record.code_object_offset;
|
|
auto itr = indexes.find(ins);
|
|
if(itr != indexes.end()) return itr->second;
|
|
auto idx = instruction_decoder.size();
|
|
auto pc_instruction = decode_instruction(record);
|
|
instruction_decoder.emplace_back(pc_instruction->inst);
|
|
instruction_comment.emplace_back(pc_instruction->comment);
|
|
indexes.emplace(ins, idx);
|
|
return idx;
|
|
}
|
|
|
|
void
|
|
metadata::add_decoder(rocprofiler_code_object_info_t* obj_data)
|
|
{
|
|
if(obj_data->storage_type == ROCPROFILER_CODE_OBJECT_STORAGE_TYPE_FILE)
|
|
{
|
|
decoder.wlock(
|
|
[](auto& _decoder, rocprofiler_code_object_info_t* obj_data_v) {
|
|
_decoder.addDecoder(obj_data_v->uri,
|
|
obj_data_v->code_object_id,
|
|
obj_data_v->load_delta,
|
|
obj_data_v->load_size);
|
|
},
|
|
obj_data);
|
|
}
|
|
else
|
|
{
|
|
decoder.wlock(
|
|
[](auto& _decoder, rocprofiler_code_object_info_t* obj_data_v) {
|
|
_decoder.addDecoder(
|
|
// NOLINTBEGIN(performance-no-int-to-ptr)
|
|
reinterpret_cast<const void*>(obj_data_v->memory_base),
|
|
// NOLINTEND(performance-no-int-to-ptr)
|
|
obj_data_v->memory_size,
|
|
obj_data_v->code_object_id,
|
|
obj_data_v->load_delta,
|
|
obj_data_v->load_size);
|
|
},
|
|
obj_data);
|
|
}
|
|
}
|
|
|
|
std::unique_ptr<instruction_t>
|
|
metadata::decode_instruction(rocprofiler_pc_t pc)
|
|
{
|
|
return decoder.wlock(
|
|
[](auto& _decoder, uint64_t id, uint64_t addr) { return _decoder.get(id, addr); },
|
|
pc.code_object_id,
|
|
pc.code_object_offset);
|
|
}
|
|
|
|
agent_index
|
|
create_agent_index(const rocprofiler::tool::agent_indexing index,
|
|
uint32_t agent_abs_index,
|
|
uint32_t agent_log_index,
|
|
uint32_t agent_type_index,
|
|
const std::string_view agent_type)
|
|
{
|
|
switch(index)
|
|
{
|
|
case rocprofiler::tool::agent_indexing::node: // absolute
|
|
{
|
|
return agent_index{"Agent", agent_abs_index, agent_type};
|
|
}
|
|
case rocprofiler::tool::agent_indexing::logical_node: // relative (default)
|
|
{
|
|
return agent_index{"Agent", agent_log_index, agent_type};
|
|
}
|
|
case rocprofiler::tool::agent_indexing::logical_node_type: // type-relative
|
|
{
|
|
return agent_index{agent_type, agent_type_index, agent_type};
|
|
}
|
|
}
|
|
|
|
ROCP_CI_LOG(WARNING) << fmt::format(
|
|
"Unsupported agent indexing {} for agent-{}", static_cast<int>(index), agent_abs_index);
|
|
return agent_index{};
|
|
}
|
|
} // namespace tool
|
|
} // namespace rocprofiler
|