Files
rocm-systems/source/lib/rocprofiler-sdk/kfd/tests/parser.cpp
T
Kuricheti, Mythreya 8a461afe20 [SDK] KFD new events API (#321)
* Remove page-migration

* Add KFD events API

* Address review comments

* Move assert checks

* Update enum-string utils

* Update codeowners

* Update KFD header

* Add perfetto category
2025-06-26 13:28:45 -05:00

275 lines
11 KiB
C++

// MIT License
//
// Copyright (c) 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 <chrono>
#include <cstddef>
#include <limits>
#include <random>
#include <string>
#include <string_view>
#include "lib/rocprofiler-sdk/kfd/defines.hpp"
#include "lib/rocprofiler-sdk/kfd/utils.hpp"
#include "rocprofiler-sdk/kfd/kfd_id.h"
#include <fmt/core.h>
#include <gtest/gtest.h>
#include <unistd.h>
namespace rocprofiler
{
namespace kfd
{
#define ROCPROFILER_LIB_ROCPROFILER_SDK_KFD_CPP_IMPL 1
#include "lib/rocprofiler-sdk/kfd/kfd.def.cpp"
#undef ROCPROFILER_LIB_ROCPROFILER_SDK_KFD_CPP_IMPL
} // namespace kfd
} // namespace rocprofiler
namespace
{
using namespace rocprofiler::kfd;
// Internally, get_node_map is called for a given gpu ID
// We are testing the parser, so use an identity mapping
const agent_id_map_t agent_map = {
{0, {0}},
{0x1ea0, {0x1ea0}},
{0xfc7d, {0xfc7d}},
{0xad5c, {0xad5c}},
};
kfd_event_record
parse(std::string_view arg)
{
size_t kfd_id = std::numeric_limits<size_t>::max();
const auto scan_count = std::sscanf(arg.data(), "%lx ", &kfd_id);
EXPECT_EQ(scan_count, 1);
EXPECT_GE(kfd_id, KFD_SMI_EVENT_MIGRATE_START);
EXPECT_LE(kfd_id, KFD_SMI_EVENT_DROPPED_EVENT);
auto event_id = to_rocprofiler_kfd_event_id_func(static_cast<rocprofiler_kfd_event_id>(kfd_id),
std::make_index_sequence<KFD_EVENT_LAST>{});
EXPECT_GE(event_id, KFD_EVENT_PAGE_MIGRATE_START);
EXPECT_LE(event_id, KFD_EVENT_DROPPED_EVENT);
return parse_event(event_id, agent_map, arg);
}
} // namespace
/* The following tests ensure that we can correctly parse and convert an event to the structured
equivalent
*/
TEST(rocprofiler_lib, parse_kfd_event_page_migrate_start)
{
using namespace rocprofiler::kfd;
const auto event = parse("5 14601738586508 -152990 @7f0f15200(2c02) 0->1ea0 1ea0:0 1");
const auto migrate_start = event.data.page_migrate_event;
EXPECT_EQ(event.kind, ROCPROFILER_BUFFER_TRACING_KFD_EVENT_PAGE_MIGRATE);
EXPECT_EQ(event.operation, ROCPROFILER_KFD_EVENT_PAGE_MIGRATE_PAGEFAULT_GPU);
EXPECT_EQ(migrate_start.kind, ROCPROFILER_BUFFER_TRACING_KFD_EVENT_PAGE_MIGRATE);
EXPECT_EQ(migrate_start.operation, ROCPROFILER_KFD_EVENT_PAGE_MIGRATE_PAGEFAULT_GPU);
EXPECT_EQ(migrate_start.timestamp, 14601738586508);
EXPECT_EQ(migrate_start.pid, 152990);
EXPECT_EQ(migrate_start.start_address.handle, 0x7f0f15200 << 12);
EXPECT_EQ(migrate_start.end_address.handle, (0x7f0f15200 + 0x2c02) << 12);
EXPECT_EQ(migrate_start.src_agent.handle, 0);
EXPECT_EQ(migrate_start.dst_agent.handle, 0x1ea0);
EXPECT_EQ(migrate_start.prefetch_agent.handle, 0x1ea0);
EXPECT_EQ(migrate_start.preferred_agent.handle, 0);
EXPECT_EQ(migrate_start.error_code, 0);
}
TEST(rocprofiler_lib, parse_kfd_event_page_migrate_end)
{
using namespace rocprofiler::kfd;
const auto event = parse("6 15202910515905 -152990 @7f0f15200(2c02) 0->1ea0 1 75");
const auto migrate_end = event.data.page_migrate_event;
EXPECT_EQ(event.kind, ROCPROFILER_BUFFER_TRACING_KFD_EVENT_PAGE_MIGRATE);
EXPECT_EQ(event.operation, ROCPROFILER_KFD_EVENT_PAGE_MIGRATE_END);
EXPECT_EQ(migrate_end.kind, ROCPROFILER_BUFFER_TRACING_KFD_EVENT_PAGE_MIGRATE);
EXPECT_EQ(migrate_end.operation, ROCPROFILER_KFD_EVENT_PAGE_MIGRATE_END);
EXPECT_EQ(migrate_end.timestamp, 15202910515905);
EXPECT_EQ(migrate_end.pid, 152990);
EXPECT_EQ(migrate_end.start_address.handle, 0x7f0f15200 << 12);
EXPECT_EQ(migrate_end.end_address.handle, (0x7f0f15200 + 0x2c02) << 12);
EXPECT_EQ(migrate_end.src_agent.handle, 0);
EXPECT_EQ(migrate_end.dst_agent.handle, 0x1ea0);
EXPECT_EQ(migrate_end.prefetch_agent.handle, 0); // Not generated for end event
EXPECT_EQ(migrate_end.preferred_agent.handle, 0); // Not generated for end event
EXPECT_EQ(migrate_end.error_code, 75);
}
TEST(rocprofiler_lib, parse_kfd_event_page_fault_start)
{
using namespace rocprofiler::kfd;
const auto event = parse("7 40507688414784 -156893 @7fa608127(ad5c) R");
const auto page_fault = event.data.page_fault_event;
EXPECT_EQ(event.kind, ROCPROFILER_BUFFER_TRACING_KFD_EVENT_PAGE_FAULT);
EXPECT_EQ(event.operation, ROCPROFILER_KFD_EVENT_PAGE_FAULT_START_READ_FAULT);
EXPECT_EQ(page_fault.kind, ROCPROFILER_BUFFER_TRACING_KFD_EVENT_PAGE_FAULT);
EXPECT_EQ(page_fault.operation, ROCPROFILER_KFD_EVENT_PAGE_FAULT_START_READ_FAULT);
EXPECT_EQ(page_fault.timestamp, 40507688414784);
EXPECT_EQ(page_fault.pid, 156893);
EXPECT_EQ(page_fault.agent_id.handle, 0xad5c);
EXPECT_EQ(page_fault.address.handle, 0x7fa608127 << 12);
}
TEST(rocprofiler_lib, parse_kfd_event_page_fault_end)
{
using namespace rocprofiler::kfd;
{
const auto event = parse("8 40507688514376 -156893 @7fa608127(ad5c) U");
const auto page_fault = event.data.page_fault_event;
EXPECT_EQ(event.kind, ROCPROFILER_BUFFER_TRACING_KFD_EVENT_PAGE_FAULT);
EXPECT_EQ(event.operation, ROCPROFILER_KFD_EVENT_PAGE_FAULT_END_PAGE_UPDATED);
EXPECT_EQ(page_fault.kind, ROCPROFILER_BUFFER_TRACING_KFD_EVENT_PAGE_FAULT);
EXPECT_EQ(page_fault.operation, ROCPROFILER_KFD_EVENT_PAGE_FAULT_END_PAGE_UPDATED);
EXPECT_EQ(page_fault.timestamp, 40507688514376);
EXPECT_EQ(page_fault.pid, 156893);
EXPECT_EQ(page_fault.agent_id.handle, 0xad5c);
EXPECT_EQ(page_fault.address.handle, 0x7fa608127 << 12);
}
{
const auto event = parse("8 40507688516386 -156898 @7fa698127(ad5c) M");
const auto page_fault = event.data.page_fault_event;
EXPECT_EQ(event.kind, ROCPROFILER_BUFFER_TRACING_KFD_EVENT_PAGE_FAULT);
EXPECT_EQ(event.operation, ROCPROFILER_KFD_EVENT_PAGE_FAULT_END_PAGE_MIGRATED);
EXPECT_EQ(page_fault.kind, ROCPROFILER_BUFFER_TRACING_KFD_EVENT_PAGE_FAULT);
EXPECT_EQ(page_fault.operation, ROCPROFILER_KFD_EVENT_PAGE_FAULT_END_PAGE_MIGRATED);
EXPECT_EQ(page_fault.timestamp, 40507688516386);
EXPECT_EQ(page_fault.pid, 156898);
EXPECT_EQ(page_fault.agent_id.handle, 0xad5c);
EXPECT_EQ(page_fault.address.handle, 0x7fa698127 << 12);
}
}
TEST(rocprofiler_lib, parse_kfd_event_queue_eviction)
{
using namespace rocprofiler::kfd;
{
const auto event = parse("9 38086928279363 -125752 1ea0 1");
const auto queue_event = event.data.queue_event;
EXPECT_EQ(event.kind, ROCPROFILER_BUFFER_TRACING_KFD_EVENT_QUEUE);
EXPECT_EQ(event.operation, ROCPROFILER_KFD_EVENT_QUEUE_EVICT_USERPTR);
EXPECT_EQ(queue_event.kind, ROCPROFILER_BUFFER_TRACING_KFD_EVENT_QUEUE);
EXPECT_EQ(queue_event.operation, ROCPROFILER_KFD_EVENT_QUEUE_EVICT_USERPTR);
EXPECT_EQ(queue_event.timestamp, 38086928279363);
EXPECT_EQ(queue_event.pid, 125752);
EXPECT_EQ(queue_event.agent_id.handle, 0x1ea0);
}
{
const auto event = parse("9 38086928279363 -125752 1ea0 3");
const auto queue_event = event.data.queue_event;
EXPECT_EQ(event.kind, ROCPROFILER_BUFFER_TRACING_KFD_EVENT_QUEUE);
EXPECT_EQ(event.operation, ROCPROFILER_KFD_EVENT_QUEUE_EVICT_SUSPEND);
EXPECT_EQ(queue_event.kind, ROCPROFILER_BUFFER_TRACING_KFD_EVENT_QUEUE);
EXPECT_EQ(queue_event.operation, ROCPROFILER_KFD_EVENT_QUEUE_EVICT_SUSPEND);
EXPECT_EQ(queue_event.timestamp, 38086928279363);
EXPECT_EQ(queue_event.pid, 125752);
EXPECT_EQ(queue_event.agent_id.handle, 0x1ea0);
}
}
TEST(rocprofiler_lib, parse_kfd_event_queue_restore)
{
using namespace rocprofiler::kfd;
{
const auto event = parse("a 38652512365099 -131057 fc7d");
const auto queue_event = event.data.queue_event;
EXPECT_EQ(event.kind, ROCPROFILER_BUFFER_TRACING_KFD_EVENT_QUEUE);
EXPECT_EQ(event.operation, ROCPROFILER_KFD_EVENT_QUEUE_RESTORE);
EXPECT_EQ(queue_event.kind, ROCPROFILER_BUFFER_TRACING_KFD_EVENT_QUEUE);
EXPECT_EQ(queue_event.operation, ROCPROFILER_KFD_EVENT_QUEUE_RESTORE);
EXPECT_EQ(queue_event.timestamp, 38652512365099);
EXPECT_EQ(queue_event.pid, 131057);
EXPECT_EQ(queue_event.agent_id.handle, 0xfc7d);
}
{
const auto event = parse("a 40082605896929 -148516 fc7d R");
const auto queue_event = event.data.queue_event;
EXPECT_EQ(event.kind, ROCPROFILER_BUFFER_TRACING_KFD_EVENT_QUEUE);
EXPECT_EQ(event.operation, ROCPROFILER_KFD_EVENT_QUEUE_RESTORE_RESCHEDULED);
EXPECT_EQ(queue_event.kind, ROCPROFILER_BUFFER_TRACING_KFD_EVENT_QUEUE);
EXPECT_EQ(queue_event.operation, ROCPROFILER_KFD_EVENT_QUEUE_RESTORE_RESCHEDULED);
EXPECT_EQ(queue_event.timestamp, 40082605896929);
EXPECT_EQ(queue_event.pid, 148516);
EXPECT_EQ(queue_event.agent_id.handle, 0xfc7d);
}
}
TEST(rocprofiler_lib, parse_kfd_event_unmap_from_gpu)
{
using namespace rocprofiler::kfd;
const auto event = parse("b 15203214457186 -152990 @7f93ac200(200) 1ea0 2");
const auto unmap = event.data.unmap_event;
EXPECT_EQ(event.kind, ROCPROFILER_BUFFER_TRACING_KFD_EVENT_UNMAP_FROM_GPU);
EXPECT_EQ(event.operation, ROCPROFILER_KFD_EVENT_QUEUE_EVICT_TTM);
EXPECT_EQ(unmap.kind, ROCPROFILER_BUFFER_TRACING_KFD_EVENT_UNMAP_FROM_GPU);
EXPECT_EQ(unmap.operation, ROCPROFILER_KFD_EVENT_QUEUE_EVICT_TTM);
EXPECT_EQ(unmap.timestamp, 15203214457186);
EXPECT_EQ(unmap.pid, 152990);
EXPECT_EQ(unmap.start_address.handle, 0x7f93ac200 << 12);
EXPECT_EQ(unmap.end_address.handle, (0x7f93ac200 + 0x200) << 12);
EXPECT_EQ(unmap.agent_id.handle, 0x1ea0);
}
TEST(rocprofiler_lib, parse_kfd_event_dropped_event)
{
using namespace rocprofiler::kfd;
const auto event = parse("e 18203445217186 -323990 5");
const auto dropped = event.data.dropped_event;
EXPECT_EQ(event.kind, ROCPROFILER_BUFFER_TRACING_KFD_EVENT_DROPPED_EVENTS);
EXPECT_EQ(event.operation, ROCPROFILER_KFD_EVENT_DROPPED_EVENTS);
EXPECT_EQ(dropped.kind, ROCPROFILER_BUFFER_TRACING_KFD_EVENT_DROPPED_EVENTS);
EXPECT_EQ(dropped.operation, ROCPROFILER_KFD_EVENT_DROPPED_EVENTS);
EXPECT_EQ(dropped.timestamp, 18203445217186);
EXPECT_EQ(dropped.pid, 323990);
EXPECT_EQ(dropped.count, 5);
}