Fix agent node id + randomize offset id (#625)
* Fix agent node id + randomize offset id - fixes the node_id value - randomizes a constant offset for the id.handle values - switch to using node ids in rocprofiler-sdk-tool library - update tests related to agents * Logical node id - sequential node id values from 0 to (N-1) where N is the number of agents
This commit is contained in:
کامیت شده توسط
GitHub
والد
2f9b1767e9
کامیت
1addfed9f6
@@ -98,7 +98,14 @@ typedef struct rocprofiler_agent_mem_bank_t
|
||||
} rocprofiler_agent_mem_bank_t;
|
||||
|
||||
/**
|
||||
* @brief Agent (rocprofiler_agent_t stores the properties of an Agent)
|
||||
* @brief Stores the properties of an agent (CPU, GPU, etc.)
|
||||
*
|
||||
* The `node_id` member is the KFD topology node id. It should be considered the "universal"
|
||||
* indexing number. It is equivalent to the HSA-runtime HSA_AMD_AGENT_INFO_DRIVER_NODE_ID property
|
||||
* of a `hsa_agent_t`. The `const char*` fields (`name`, `vendor_name`, etc.) are guaranteed to be
|
||||
* valid pointers to null-terminated strings during tool finalization. Pointers to the agents via
|
||||
* @see ::rocprofiler_query_available_agents are constant and will not be deallocated until after
|
||||
* tool finalization. Making copies of the agent struct is also valid.
|
||||
*/
|
||||
typedef struct rocprofiler_agent_v0_t
|
||||
{
|
||||
@@ -187,9 +194,10 @@ typedef struct rocprofiler_agent_v0_t
|
||||
///< based on the device type.
|
||||
const rocprofiler_pc_sampling_configuration_t*
|
||||
pc_sampling_configs; ///< GPU only. Array of PC sampling configuration types.
|
||||
uint32_t node_id; ///< Node sequence number. This will be equivalent to the HSA-runtime
|
||||
///< HSA_AMD_AGENT_INFO_DRIVER_NODE_ID property
|
||||
uint32_t reserved0; ///< reserved padding
|
||||
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
|
||||
} rocprofiler_agent_v0_t;
|
||||
|
||||
typedef rocprofiler_agent_v0_t rocprofiler_agent_t;
|
||||
|
||||
@@ -311,6 +311,7 @@ using kernel_symbol_data_map_t = std::unordered_map<rocprofiler_kernel_id_t, ker
|
||||
using targeted_kernels_set_t = std::unordered_set<rocprofiler_kernel_id_t>;
|
||||
using counter_dimension_info_map_t =
|
||||
std::unordered_map<uint64_t, std::vector<rocprofiler_record_dimension_info_t>>;
|
||||
using agent_info_map_t = std::unordered_map<rocprofiler_agent_id_t, const rocprofiler_agent_t*>;
|
||||
|
||||
auto code_obj_data = common::Synchronized<code_object_data_map_t, true>{};
|
||||
auto kernel_data = common::Synchronized<kernel_symbol_data_map_t, true>{};
|
||||
@@ -319,6 +320,7 @@ auto target_kernels = common::Synchronized<targeted_kernels_set_t>{};
|
||||
auto dispatch_index = std::atomic<uint64_t>{0};
|
||||
auto* buffered_name_info = as_pointer(get_buffer_id_names());
|
||||
auto* callback_name_info = as_pointer(get_callback_id_names());
|
||||
auto* agent_info = as_pointer(agent_info_map_t{});
|
||||
|
||||
bool
|
||||
add_kernel_target(uint64_t _kern_id)
|
||||
@@ -661,7 +663,7 @@ buffered_tracing_callback(rocprofiler_context_id_t /*context*/,
|
||||
tool::csv::kernel_trace_csv_encoder::write_row(
|
||||
kernel_trace_ss,
|
||||
CHECK_NOTNULL(buffered_name_info)->kind_names.at(record->kind),
|
||||
record->agent_id.handle,
|
||||
agent_info->at(record->agent_id)->node_id,
|
||||
record->queue_id.handle,
|
||||
record->kernel_id,
|
||||
std::move(kernel_name),
|
||||
@@ -714,8 +716,8 @@ buffered_tracing_callback(rocprofiler_context_id_t /*context*/,
|
||||
CHECK_NOTNULL(buffered_name_info)
|
||||
->operation_names.at(record->kind)
|
||||
.at(record->operation),
|
||||
record->src_agent_id.handle,
|
||||
record->dst_agent_id.handle,
|
||||
agent_info->at(record->src_agent_id)->node_id,
|
||||
agent_info->at(record->dst_agent_id)->node_id,
|
||||
record->correlation_id.internal,
|
||||
record->start_timestamp,
|
||||
record->end_timestamp);
|
||||
@@ -931,7 +933,7 @@ counter_record_callback(rocprofiler_profile_counting_dispatch_data_t dispatch_da
|
||||
csv_encoder::write_row(counter_collection_ss,
|
||||
correlation_id.internal,
|
||||
cnt_dispatch_data_v->dispatch_index,
|
||||
dispatch_data.agent_id.handle,
|
||||
agent_info->at(dispatch_data.agent_id)->node_id,
|
||||
dispatch_data.queue_id.handle,
|
||||
getpid(),
|
||||
cnt_dispatch_data_v->thread_id,
|
||||
@@ -1321,6 +1323,21 @@ rocprofiler_configure(uint32_t version,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ROCPROFILER_CALL(
|
||||
rocprofiler_query_available_agents(
|
||||
ROCPROFILER_AGENT_INFO_VERSION_0,
|
||||
[](rocprofiler_agent_version_t, const void** agents, size_t num_agents, void*) {
|
||||
for(size_t i = 0; i < num_agents; ++i)
|
||||
{
|
||||
auto* agent = static_cast<const rocprofiler_agent_v0_t*>(agents[i]);
|
||||
agent_info->emplace(agent->id, agent);
|
||||
}
|
||||
return ROCPROFILER_STATUS_SUCCESS;
|
||||
},
|
||||
sizeof(rocprofiler_agent_t),
|
||||
nullptr),
|
||||
"Iterate rocporfiler agents")
|
||||
|
||||
LOG(INFO) << id->name << " is using rocprofiler-sdk v" << major << "." << minor << "." << patch
|
||||
<< " (" << runtime_version << ")";
|
||||
|
||||
|
||||
@@ -27,18 +27,24 @@
|
||||
#include "lib/common/filesystem.hpp"
|
||||
#include "lib/common/scope_destructor.hpp"
|
||||
#include "lib/common/static_object.hpp"
|
||||
#include "lib/common/utility.hpp"
|
||||
#include "lib/rocprofiler-sdk/agent.hpp"
|
||||
#include "lib/rocprofiler-sdk/hsa/agent_cache.hpp"
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/ranges.h>
|
||||
#include <glog/logging.h>
|
||||
#include <hsa/hsa.h>
|
||||
#include <hsa/hsa_api_trace.h>
|
||||
#include <libdrm/amdgpu.h>
|
||||
#include <xf86drm.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <limits>
|
||||
#include <random>
|
||||
#include <regex>
|
||||
#include <set>
|
||||
#include <shared_mutex>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
@@ -92,6 +98,18 @@ get_string_entry(std::string_view name)
|
||||
.second.get();
|
||||
}
|
||||
|
||||
uint64_t
|
||||
get_agent_offset()
|
||||
{
|
||||
static uint64_t _v = []() {
|
||||
auto gen = std::mt19937{std::random_device{}()};
|
||||
auto rng = std::uniform_int_distribution<uint64_t>{std::numeric_limits<uint8_t>::max(),
|
||||
std::numeric_limits<uint16_t>::max()};
|
||||
return rng(gen);
|
||||
}();
|
||||
return _v;
|
||||
}
|
||||
|
||||
struct cpu_info
|
||||
{
|
||||
long processor = -1;
|
||||
@@ -377,8 +395,8 @@ read_topology()
|
||||
|
||||
while(true)
|
||||
{
|
||||
auto idx = idcount++;
|
||||
auto node_path = sysfs_nodes_path / std::to_string(idx);
|
||||
auto node_id = nodecount++;
|
||||
auto node_path = sysfs_nodes_path / std::to_string(node_id);
|
||||
// assumes that nodes are monotonically increasing and thus once we are missing a node
|
||||
// folder for a number, there are no more nodes
|
||||
if(!fs::exists(node_path)) break;
|
||||
@@ -403,13 +421,11 @@ read_topology()
|
||||
// we may have been able to open the properties file but if it was empty, we ignore it
|
||||
if(properties.empty()) continue;
|
||||
|
||||
auto agent_info = rocprofiler_agent_t{};
|
||||
memset(&agent_info, 0, sizeof(agent_info));
|
||||
|
||||
agent_info.size = sizeof(rocprofiler_agent_t);
|
||||
agent_info.id.handle = idx;
|
||||
agent_info.type = ROCPROFILER_AGENT_TYPE_NONE;
|
||||
agent_info.node_id = nodecount++;
|
||||
auto agent_info = common::init_public_api_struct(rocprofiler_agent_t{});
|
||||
agent_info.type = ROCPROFILER_AGENT_TYPE_NONE;
|
||||
agent_info.logical_node_id = idcount++;
|
||||
agent_info.node_id = node_id;
|
||||
agent_info.id.handle = (agent_info.logical_node_id) + get_agent_offset();
|
||||
|
||||
if(!name_prop.empty())
|
||||
agent_info.model_name =
|
||||
@@ -705,9 +721,57 @@ construct_agent_cache(::HsaApiTable* table)
|
||||
},
|
||||
&hsa_agents);
|
||||
|
||||
ROCP_CI_LOG_IF(ERROR, rocp_agents.size() != hsa_agents.size())
|
||||
auto get_hsa_status_string = [table](hsa_status_t _status) -> std::string_view {
|
||||
const char* _status_msg = nullptr;
|
||||
return (table->core_->hsa_status_string_fn(_status, &_status_msg) == HSA_STATUS_SUCCESS &&
|
||||
_status_msg)
|
||||
? std::string_view{_status_msg}
|
||||
: std::string_view{"(unknown HSA error)"};
|
||||
};
|
||||
|
||||
auto rocp_hsa_agent_node_ids = std::set<uint32_t>{};
|
||||
if(rocp_agents.size() != hsa_agents.size())
|
||||
{
|
||||
for(auto hitr : hsa_agents)
|
||||
{
|
||||
auto internal_node_id = std::numeric_limits<uint32_t>::max();
|
||||
auto ret = table->core_->hsa_agent_get_info_fn(
|
||||
hitr,
|
||||
static_cast<hsa_agent_info_t>(HSA_AMD_AGENT_INFO_DRIVER_NODE_ID),
|
||||
&internal_node_id);
|
||||
|
||||
LOG_IF(ERROR, ret != HSA_STATUS_SUCCESS)
|
||||
<< "hsa_agent_get_info(hsa_agent_t=" << hitr.handle
|
||||
<< ", HSA_AMD_AGENT_INFO_DRIVER_NODE_ID, ...) returned " << ret
|
||||
<< " :: " << get_hsa_status_string(ret);
|
||||
|
||||
if(ret == HSA_STATUS_SUCCESS)
|
||||
{
|
||||
{
|
||||
auto ret_emplace = rocp_hsa_agent_node_ids.emplace(internal_node_id).second;
|
||||
LOG_IF(WARNING, !ret_emplace)
|
||||
<< "duplicate internal node id " << internal_node_id;
|
||||
}
|
||||
|
||||
for(const auto* ritr : rocp_agents)
|
||||
{
|
||||
if(ritr->node_id == internal_node_id)
|
||||
{
|
||||
rocp_hsa_agent_node_ids.erase(internal_node_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG_IF(FATAL, !rocp_hsa_agent_node_ids.empty())
|
||||
<< "Found " << rocp_agents.size() << " rocprofiler agents and " << hsa_agents.size()
|
||||
<< " HSA agents";
|
||||
<< " HSA agents. HSA agents contained " << rocp_hsa_agent_node_ids.size()
|
||||
<< " internal node ids not found by rocprofiler: "
|
||||
<< fmt::format(
|
||||
"{}",
|
||||
fmt::join(rocp_hsa_agent_node_ids.begin(), rocp_hsa_agent_node_ids.end(), ", "));
|
||||
|
||||
get_agent_mapping().reserve(get_agent_mapping().size() + rocp_agents.size());
|
||||
|
||||
@@ -745,7 +809,9 @@ construct_agent_cache(::HsaApiTable* table)
|
||||
}
|
||||
}
|
||||
|
||||
LOG_IF(ERROR, agent_map.size() != hsa_agents.size())
|
||||
LOG(ERROR) << "# agent node maps: " << hsa_agent_node_map.size();
|
||||
|
||||
LOG_IF(FATAL, agent_map.size() != hsa_agents.size())
|
||||
<< "rocprofiler was only able to map " << agent_map.size()
|
||||
<< " rocprofiler agents to HSA agents, expected " << hsa_agents.size();
|
||||
|
||||
@@ -833,8 +899,10 @@ construct_agent_cache(::HsaApiTable* table)
|
||||
std::optional<hsa_agent_t>
|
||||
get_hsa_agent(const rocprofiler_agent_t* agent)
|
||||
{
|
||||
LOG(ERROR) << "# of agent mappings: " << get_agent_mapping().size();
|
||||
for(const auto& itr : get_agent_mapping())
|
||||
{
|
||||
LOG(ERROR) << "checking " << itr.rocp_agent->id.handle << " vs. " << agent->id.handle;
|
||||
if(itr.rocp_agent->id.handle == agent->id.handle) return itr.hsa_agent;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,11 +24,14 @@
|
||||
#include <rocprofiler-sdk/fwd.h>
|
||||
#include <rocprofiler-sdk/registration.h>
|
||||
|
||||
#include "lib/rocprofiler-sdk/agent.hpp"
|
||||
#include "lib/rocprofiler-sdk/registration.hpp"
|
||||
#include "lib/rocprofiler-sdk/tests/details/agent.hpp"
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <hsa/hsa.h>
|
||||
#include <hsa/hsa_api_trace.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <cstdint>
|
||||
@@ -101,7 +104,7 @@ TEST(rocprofiler_lib, agent_abi)
|
||||
EXPECT_EQ(offsetof(rocprofiler_agent_t, num_pc_sampling_configs), 280) << msg;
|
||||
EXPECT_EQ(offsetof(rocprofiler_agent_t, pc_sampling_configs), 288) << msg;
|
||||
EXPECT_EQ(offsetof(rocprofiler_agent_t, node_id), 296) << msg;
|
||||
EXPECT_EQ(offsetof(rocprofiler_agent_t, reserved0), 300) << msg;
|
||||
EXPECT_EQ(offsetof(rocprofiler_agent_t, logical_node_id), 300) << msg;
|
||||
// Add test for offset of new field above this. Do NOT change any existing values!
|
||||
|
||||
constexpr auto expected_rocp_agent_size = 304;
|
||||
@@ -145,7 +148,6 @@ TEST(rocprofiler_lib, agent)
|
||||
if(agents_ver != ROCPROFILER_AGENT_INFO_VERSION_0) return ROCPROFILER_STATUS_ERROR;
|
||||
|
||||
auto* agents_v = static_cast<std::vector<const rocprofiler_agent_t*>*>(user_data);
|
||||
// EXPECT_EQ(num_agents, hsa_agents_v.size());
|
||||
for(size_t i = 0; i < num_agents; ++i)
|
||||
{
|
||||
const auto* agent = static_cast<const rocprofiler_agent_t*>(agents_arr[i]);
|
||||
@@ -154,6 +156,26 @@ TEST(rocprofiler_lib, agent)
|
||||
return ROCPROFILER_STATUS_SUCCESS;
|
||||
};
|
||||
|
||||
hsa_init();
|
||||
{
|
||||
auto table = ::HsaApiTable{};
|
||||
auto core_table = ::CoreApiTable{};
|
||||
auto amd_ext_table = ::AmdExtTable{};
|
||||
|
||||
memset(&table, 0, sizeof(table));
|
||||
memset(&core_table, 0, sizeof(core_table));
|
||||
memset(&amd_ext_table, 0, sizeof(amd_ext_table));
|
||||
|
||||
core_table.hsa_iterate_agents_fn = &hsa_iterate_agents;
|
||||
core_table.hsa_status_string_fn = &hsa_status_string;
|
||||
core_table.hsa_agent_get_info_fn = &hsa_agent_get_info;
|
||||
amd_ext_table.hsa_amd_agent_iterate_memory_pools_fn = &hsa_amd_agent_iterate_memory_pools;
|
||||
amd_ext_table.hsa_amd_memory_pool_get_info_fn = &hsa_amd_memory_pool_get_info;
|
||||
table.core_ = &core_table;
|
||||
table.amd_ext_ = &amd_ext_table;
|
||||
rocprofiler::agent::construct_agent_cache(&table);
|
||||
}
|
||||
|
||||
std::cout << "# querying available agents...\n" << std::flush;
|
||||
auto status =
|
||||
rocprofiler_query_available_agents(ROCPROFILER_AGENT_INFO_VERSION_0,
|
||||
@@ -168,10 +190,12 @@ TEST(rocprofiler_lib, agent)
|
||||
|
||||
auto& hsa_agents_v = _rocm_info.agents;
|
||||
|
||||
ASSERT_EQ(agents.size(), hsa_agents_v.size());
|
||||
for(size_t i = 0; i < agents.size(); ++i)
|
||||
EXPECT_GE(agents.size(), hsa_agents_v.size());
|
||||
|
||||
uint64_t skipped = 0;
|
||||
for(const auto* agent : agents)
|
||||
{
|
||||
const auto* agent = agents.at(i);
|
||||
ASSERT_NE(agent, nullptr);
|
||||
|
||||
auto msg = fmt::format("name={}, model={}, gfx version={}, id={}, type={}",
|
||||
agent->name,
|
||||
@@ -180,11 +204,26 @@ TEST(rocprofiler_lib, agent)
|
||||
agent->node_id,
|
||||
agent->type == ROCPROFILER_AGENT_TYPE_CPU ? "CPU" : "GPU");
|
||||
|
||||
// std::cout << msg << std::endl;
|
||||
EXPECT_LT(i, hsa_agents_v.size()) << msg;
|
||||
if(i >= hsa_agents_v.size()) continue;
|
||||
rocprofiler::test::agent_info_t* hsa_agent = nullptr;
|
||||
{
|
||||
auto _hsa_agent = rocprofiler::agent::get_hsa_agent(agent);
|
||||
|
||||
auto* hsa_agent = &hsa_agents_v.at(i);
|
||||
if(!_hsa_agent)
|
||||
{
|
||||
++skipped;
|
||||
continue;
|
||||
}
|
||||
|
||||
for(auto& hitr : hsa_agents_v)
|
||||
{
|
||||
if(_hsa_agent && _hsa_agent->handle == hitr.hsa_agent.handle)
|
||||
{
|
||||
hsa_agent = &hitr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT_NE(hsa_agent, nullptr) << msg;
|
||||
}
|
||||
|
||||
if(agent->type == ROCPROFILER_AGENT_TYPE_CPU)
|
||||
{
|
||||
@@ -238,6 +277,8 @@ TEST(rocprofiler_lib, agent)
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ(skipped, (agents.size() - hsa_agents_v.size()));
|
||||
|
||||
// clean up memory leak
|
||||
for(auto& itr : _rocm_info.isas)
|
||||
delete[] itr.name_str;
|
||||
|
||||
@@ -103,6 +103,9 @@ AcquireSystemInfo(system_info_t* sys_info)
|
||||
hsa_status_t
|
||||
AcquireAgentInfoEntry(hsa_agent_t agent, agent_info_t* agent_i)
|
||||
{
|
||||
// store the hsa_agent_t value
|
||||
agent_i->hsa_agent = agent;
|
||||
|
||||
hsa_status_t err;
|
||||
// Get agent name and vendor
|
||||
err = hsa_agent_get_info(agent, HSA_AGENT_INFO_NAME, agent_i->name);
|
||||
|
||||
@@ -56,6 +56,7 @@ struct system_info_t
|
||||
// calls, and is later used for reference when displaying the information.
|
||||
struct agent_info_t
|
||||
{
|
||||
hsa_agent_t hsa_agent = {.handle = 0};
|
||||
char name[64] = {'\0'};
|
||||
char vendor_name[64] = {'\0'};
|
||||
char device_mkt_name[64] = {'\0'};
|
||||
|
||||
@@ -487,6 +487,7 @@ save(ArchiveT& ar, const rocprofiler_agent_t& data)
|
||||
SAVE_DATA_CSTR(model_name);
|
||||
SAVE_DATA_FIELD(num_pc_sampling_configs);
|
||||
SAVE_DATA_FIELD(node_id);
|
||||
SAVE_DATA_FIELD(logical_node_id);
|
||||
|
||||
auto generate = [&](auto name, const auto* value, uint64_t size) {
|
||||
using value_type = std::remove_const_t<std::remove_pointer_t<decltype(value)>>;
|
||||
|
||||
@@ -68,13 +68,13 @@ def test_memory_copy_trace(memory_copy_input_data):
|
||||
row = memory_copy_input_data[0]
|
||||
assert row["Direction"] == "HOST_TO_DEVICE"
|
||||
assert int(row["Source_Agent_Id"]) == 0
|
||||
assert int(row["Destination_Agent_Id"]) == 1
|
||||
assert int(row["Destination_Agent_Id"]) >= 1
|
||||
assert int(row["Correlation_Id"]) > 0
|
||||
assert int(row["End_Timestamp"]) >= int(row["Start_Timestamp"])
|
||||
|
||||
row = memory_copy_input_data[1]
|
||||
assert row["Direction"] == "DEVICE_TO_HOST"
|
||||
assert int(row["Source_Agent_Id"]) == 1
|
||||
assert int(row["Source_Agent_Id"]) >= 1
|
||||
assert int(row["Destination_Agent_Id"]) == 0
|
||||
assert int(row["Correlation_Id"]) > 0
|
||||
assert int(row["End_Timestamp"]) >= int(row["Start_Timestamp"])
|
||||
|
||||
مرجع در شماره جدید
Block a user