Incremental Counter Profile Creation (#933)

* Incremental Counter Profile Creation

Adds support for incremental counter creation. How this functions is the
behavior of rocprofiler_create_profile_config has been changed.

rocprofiler_create_profile_config(rocprofiler_agent_id_t           agent_id,
                                  rocprofiler_counter_id_t*        counters_list,
                                  size_t                           counters_count,
                                  rocprofiler_profile_config_id_t* config_id)

The behavior of this function now allows an existing config_id to be
supplied via config_id. The counters contained in this config will be
copied over and used as a base for a new config along with any counters
supplied in counters_list. The new config id is returned via config_id
and can be used in future dispatch/agent counting sessions.

A new config is created over modifying an existing config since there
is no gaurentee that the existing config isn't already in use. While we
could add locks (or other mutual exclusion properties) to check if its
in use and reject an update, the benefit from doing so is minor in
comparison to just creating a new config. This also side steps a common
pattern a tool may use to add additional counters at some point later on
during execution. Now they can do that without destroying the existing
config.

---------

Co-authored-by: Benjamin Welton <ben@amd.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Benjamin Welton
2024-06-19 00:11:03 -07:00
committato da GitHub
parent ab92bef1a4
commit 81d1407565
12 ha cambiato i file con 140 aggiunte e 46 eliminazioni
@@ -672,6 +672,68 @@ TEST(core, start_stop_callback_ctx)
context::pop_client(1);
}
TEST(core, test_profile_incremental)
{
ASSERT_EQ(hsa_init(), HSA_STATUS_SUCCESS);
test_init();
ASSERT_TRUE(hsa::get_queue_controller() != nullptr);
auto agents = hsa::get_queue_controller()->get_supported_agents();
ASSERT_GT(agents.size(), 0);
for(const auto& [_, agent] : agents)
{
auto metrics = findDeviceMetrics(agent, {});
ASSERT_FALSE(metrics.empty());
ASSERT_TRUE(agent.get_rocp_agent());
std::map<std::string, std::vector<counters::Metric>> metric_blocks;
for(const auto& metric : metrics)
{
if(!metric.block().empty())
{
metric_blocks[metric.block()].push_back(metric);
}
}
rocprofiler_profile_config_id_t cfg_id = {};
// Add one counter from each block to incrementally to make sure we can
// add them incrementally
for(const auto& [block_name, block_metrics] : metric_blocks)
{
rocprofiler_profile_config_id_t old_id = cfg_id;
rocprofiler_counter_id_t id = {.handle = block_metrics.front().id()};
ROCPROFILER_CALL(
rocprofiler_create_profile_config(agent.get_rocp_agent()->id, &id, 1, &cfg_id),
"Unable to create profile incrementally when we should be able to");
EXPECT_NE(old_id.handle, cfg_id.handle)
<< "We expect that the handle changes this is due to the existing profile being "
"unmodifiable after creation: "
<< block_name;
}
// Check that we encounter an error of exceeds hardware limits eventually
auto status = ROCPROFILER_STATUS_SUCCESS;
for(const auto& metric : metrics)
{
/**
* Check profile construction
*/
rocprofiler_counter_id_t id = {.handle = metric.id()};
if(status =
rocprofiler_create_profile_config(agent.get_rocp_agent()->id, &id, 1, &cfg_id);
status != ROCPROFILER_STATUS_SUCCESS)
{
break;
}
}
EXPECT_EQ(status, ROCPROFILER_STATUS_ERROR_EXCEEDS_HW_LIMIT);
}
registration::set_init_status(1);
registration::finalize();
}
TEST(core, public_api_iterate_agents)
{
ASSERT_EQ(hsa_init(), HSA_STATUS_SUCCESS);