Reimplement rocpd conversion to otf2 in Python (#1051)

Этот коммит содержится в:
Marko Crnobrnja Maletić
2025-12-05 18:58:43 +01:00
коммит произвёл GitHub
родитель 9baa65a8b7
Коммит d18ab20f7d
5 изменённых файлов: 431 добавлений и 1122 удалений
-142
Просмотреть файл
@@ -25,7 +25,6 @@
#include "lib/python/rocpd/source/common.hpp"
#include "lib/python/rocpd/source/functions.hpp"
#include "lib/python/rocpd/source/interop.hpp"
#include "lib/python/rocpd/source/otf2.hpp"
#include "lib/python/rocpd/source/perfetto.hpp"
#include "lib/python/rocpd/source/serialization/sql.hpp"
#include "lib/python/rocpd/source/sql_generator.hpp"
@@ -508,147 +507,6 @@ PYBIND11_MODULE(libpyrocpd, pyrocpd)
},
"Write pftrace output file from rocpd SQLite3 database");
pyrocpd.def(
"write_otf2",
[](rocpd::RocpdImportData& data, const tool::output_config& output_cfg) {
auto _create_agent_index =
[&output_cfg](const rocpd::types::agent& _agent) -> tool::agent_index {
auto ret_index = tool::create_agent_index(
output_cfg.agent_index_value,
_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
std::string_view(_agent.type));
return ret_index;
};
constexpr auto kernels_order_by =
"agent_abs_index ASC, stream_id ASC, queue_id ASC, start ASC, end DESC";
// to initialise the OTF@ session properly we need to know:
// (1) the process with the earliest start time
// (2) find the process with the longest duration
uint64_t min_start_time = std::numeric_limits<uint64_t>::max();
uint64_t max_fini_time = std::numeric_limits<uint64_t>::min();
for(auto obj : {data.connection})
{
auto* conn = rocpd::interop::get_connection(std::move(obj));
// min start
sqlite3_stmt* _stmt_min_start_max_fini = nullptr;
uint64_t _min_start_time = std::numeric_limits<uint64_t>::max();
uint64_t _max_fini_time = std::numeric_limits<uint64_t>::min();
sqlite3_prepare_v2(conn,
"SELECT MIN(start), MAX(fini) FROM processes;",
-1,
&_stmt_min_start_max_fini,
nullptr);
if(sqlite3_step(_stmt_min_start_max_fini) == SQLITE_ROW)
{
_min_start_time =
static_cast<uint64_t>(sqlite3_column_int64(_stmt_min_start_max_fini, 0));
_max_fini_time =
static_cast<uint64_t>(sqlite3_column_int64(_stmt_min_start_max_fini, 1));
}
sqlite3_finalize(_stmt_min_start_max_fini);
min_start_time = std::min(min_start_time, _min_start_time);
max_fini_time = std::max(max_fini_time, _max_fini_time);
}
auto otf2_session =
rocpd::output::OTF2Session(output_cfg, min_start_time, max_fini_time);
auto sqlgen_otf2 = common::simple_timer{
fmt::format("OTF2 generation from {} SQL database(s)", data.size())};
uint16_t _process_counter = 0;
for(auto obj : {data.connection})
{
auto* conn = rocpd::interop::get_connection(std::move(obj));
auto nodes = rocpd::read<rocpd::types::node>(conn);
for(const auto& nitr : nodes)
{
auto agents = rocpd::read<rocpd::types::agent>(
conn, fmt::format("WHERE guid = '{}' AND nid = {}", nitr.guid, nitr.id));
auto processes = rocpd::read<rocpd::types::process>(
conn, fmt::format("WHERE guid = '{}' AND nid = {}", nitr.guid, nitr.id));
// absolute_index |-> (agent, agent_index)
auto agents_map = std::unordered_map<uint64_t, rocpd::output::extended_agent>{};
for(const auto& itr : agents)
{
const rocprofiler::tool::agent_index new_index = _create_agent_index(itr);
const std::string labeled_name = fmt::format("{}", itr.name);
agents_map.emplace(
itr.absolute_index,
rocpd::output::extended_agent{itr, new_index, labeled_name});
}
for(const auto& pitr : processes)
{
ROCP_FATAL_IF(pitr.nid != nitr.id || pitr.guid != nitr.guid)
<< fmt::format("Found process with a mismatched nid/guid. process: "
"{}/{} vs. node: {}/{}",
pitr.nid,
pitr.guid,
nitr.id,
nitr.guid);
auto select_guid_nid_pid =
[&nitr, &pitr](std::string_view tbl,
std::string_view where_extra_condition = "") {
return fmt::format("SELECT * FROM {} WHERE guid = '{}' AND "
"nid = {} AND pid = {} {}",
tbl,
pitr.guid,
nitr.id,
pitr.pid,
where_extra_condition);
};
constexpr auto region_order_by = "start ASC, end DESC";
auto _sqlgen_otf2 = common::simple_timer{fmt::format(
"OTF2 generation from SQL for process {} (total)", pitr.pid)};
auto kernels = rocpd::sql_generator<rocpd::types::kernel_dispatch>{
conn, select_guid_nid_pid("kernels"), kernels_order_by};
auto memory_allocations =
rocpd::sql_generator<rocpd::types::memory_allocation>{
conn, select_guid_nid_pid("memory_allocations"), region_order_by};
auto memory_copies = rocpd::sql_generator<rocpd::types::memory_copies>{
conn, select_guid_nid_pid("memory_copies"), region_order_by};
auto regions = rocpd::sql_generator<rocpd::types::region>{
conn, select_guid_nid_pid("regions"), region_order_by};
auto threads = rocpd::sql_generator<rocpd::types::thread>{
conn, select_guid_nid_pid("threads")};
ROCP_TRACE << "Starting OTF2 generation from SQL for process " << pitr.pid;
auto _sqlgen_perfw = common::simple_timer{fmt::format(
"OTF2 generation from SQL for process {} (write)", pitr.pid)};
rocpd::output::write_otf2(otf2_session,
pitr,
_process_counter,
agents_map,
threads,
regions,
kernels,
memory_copies,
memory_allocations);
_process_counter++;
}
}
}
},
"Write OTF2 output file from rocpd SQLite3 database");
// NOLINTEND(performance-unnecessary-value-param)
// reads in all the agent info from database