Files
rocm-systems/projects/rocprofiler-sdk/samples/counter_collection/print_functional_counters.cpp
T
Jonathan R. Madsen fafab6b713 Use -sdk suffix and reset VERSION to 0.0.0 (#263)
* Fix find_package(rocprofiler) in build tree

* Move include/rocprofiler to include/rocprofiler-sdk

* Update include/CMakeLists.txt

- add_subdirectory(rocprofiler-sdk)

* Move lib/rocprofiler to lib/rocprofiler-sdk

* Move lib/rocprofiler-tool to lib/rocprofiler-sdk-tool

* Update lib/CMakeLists.txt

- add_subdirectory(rocprofiler-sdk)
- add_subdirectory(rocprofiler-sdk-tool)

* Update lib/rocprofiler-sdk/CMakeLists.txt

* Rename rocprofiler-tool to rocprofiler-sdk-tool

* Replace include rocprofiler/ with include rocprofiler-sdk/

* Replace include lib/rocprofiler/ with include lib/rocprofiler-sdk/

* Set VERSION to 0.0.0 and finish install to rocprofiler-sdk

* More fixes for rocprofiler -> rocprofiler-sdk

- fix issue with rocprofiler-sdk-config.cmake.in
- fix counters xml install path

* Fix documentation generation

* Create rocprofiler_LIB_ROCPROFILER_SDK_DIR for build tree

* cmake formatting (cmake-format) (#264)

Co-authored-by: jrmadsen <jrmadsen@users.noreply.github.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

[ROCm/rocprofiler-sdk commit: 9a0c84efa6]
2023-11-29 20:43:18 -06:00

280 строки
9.6 KiB
C++

#include "client.hpp"
#include <unistd.h>
#include <map>
#include <mutex>
#include <optional>
#include <set>
#include <shared_mutex>
#include <sstream>
#include <unordered_map>
#include <vector>
#include <rocprofiler-sdk/registration.h>
#include <rocprofiler-sdk/rocprofiler.h>
/**
* Tests the collection of all counters on the agent the test is run on.
*/
#define ROCPROFILER_CALL(result, msg) \
{ \
rocprofiler_status_t CHECKSTATUS = result; \
if(CHECKSTATUS != ROCPROFILER_STATUS_SUCCESS) \
{ \
std::string status_msg = rocprofiler_get_status_string(CHECKSTATUS); \
std::cerr << "[" #result "][" << __FILE__ << ":" << __LINE__ << "] " << msg \
<< " failed with error code " << CHECKSTATUS << ": " << status_msg \
<< std::endl; \
std::stringstream errmsg{}; \
errmsg << "[" #result "][" << __FILE__ << ":" << __LINE__ << "] " << msg " failure (" \
<< status_msg << ")"; \
throw std::runtime_error(errmsg.str()); \
} \
}
int
start()
{
return 1;
}
namespace
{
rocprofiler_context_id_t&
get_client_ctx()
{
static rocprofiler_context_id_t ctx;
return ctx;
}
rocprofiler_buffer_id_t&
get_buffer()
{
static rocprofiler_buffer_id_t buf = {};
return buf;
}
struct CaptureRecords
{
std::shared_mutex m_mutex{};
// <counter id handle, expected instances>
std::map<uint64_t, size_t> expected{};
std::map<uint64_t, std::string> expected_counter_names{};
std::vector<rocprofiler_counter_id_t> remaining{};
// <counter_id handle, instances seen>
std::map<uint64_t, size_t> captured{};
};
CaptureRecords* REC = new CaptureRecords;
CaptureRecords*
get_capture()
{
return REC;
}
void
buffered_callback(rocprofiler_context_id_t,
rocprofiler_buffer_id_t,
rocprofiler_record_header_t** headers,
size_t num_headers,
void*,
uint64_t)
{
auto& cap = *get_capture();
auto wlock = std::unique_lock{cap.m_mutex};
std::map<uint64_t, size_t> seen_counters;
for(size_t i = 0; i < num_headers; ++i)
{
auto* header = headers[i];
if(header->category == ROCPROFILER_BUFFER_CATEGORY_COUNTERS && header->kind == 0)
{
rocprofiler_counter_id_t counter;
auto* record = static_cast<rocprofiler_record_counter_t*>(header->payload);
rocprofiler_query_record_counter_id(record->id, &counter);
if(counter.handle == 517)
{
std::clog << "HERE";
}
seen_counters.emplace(counter.handle, 0).first->second++;
}
}
for(const auto& [counter_id, instances] : seen_counters)
{
cap.captured.emplace(counter_id, 0).first->second += instances;
}
}
void
dispatch_callback(rocprofiler_queue_id_t /*queue_id*/,
const rocprofiler_agent_t* agent,
rocprofiler_correlation_id_t /*correlation_id*/,
const hsa_kernel_dispatch_packet_t* /*dispatch_packet*/,
void* /*callback_data_args*/,
rocprofiler_profile_config_id_t* config)
{
auto& cap = *get_capture();
auto wlock = std::unique_lock{cap.m_mutex};
if(cap.expected.empty())
{
std::vector<rocprofiler_counter_id_t> counters_needed;
ROCPROFILER_CALL(
rocprofiler_iterate_agent_supported_counters(
*agent,
[](rocprofiler_counter_id_t* counters, size_t num_counters, void* user_data) {
std::vector<rocprofiler_counter_id_t>* vec =
static_cast<std::vector<rocprofiler_counter_id_t>*>(user_data);
for(size_t i = 0; i < num_counters; i++)
{
vec->push_back(counters[i]);
}
return ROCPROFILER_STATUS_SUCCESS;
},
static_cast<void*>(&counters_needed)),
"Could not fetch supported counters");
for(auto& found_counter : counters_needed)
{
size_t expected = 0;
rocprofiler_query_counter_instance_count(*agent, found_counter, &expected);
cap.remaining.push_back(found_counter);
cap.expected.emplace(found_counter.handle, expected);
const char* name;
size_t name_size;
ROCPROFILER_CALL(rocprofiler_query_counter_name(found_counter, &name, &name_size),
"Could not query name");
cap.expected_counter_names.emplace(found_counter.handle, std::string(name));
}
if(cap.expected.empty())
{
std::clog << "No counters found for agent - " << agent->name;
}
}
if(cap.remaining.empty()) return;
rocprofiler_profile_config_id_t profile;
ROCPROFILER_CALL(
rocprofiler_create_profile_config(*agent, &(cap.remaining.back()), 1, &profile),
"Could not construct profile cfg");
cap.remaining.pop_back();
*config = profile;
}
int
tool_init(rocprofiler_client_finalize_t, void*)
{
get_capture();
ROCPROFILER_CALL(rocprofiler_create_context(&get_client_ctx()), "context creation failed");
ROCPROFILER_CALL(rocprofiler_create_buffer(get_client_ctx(),
4096,
2048,
ROCPROFILER_BUFFER_POLICY_LOSSLESS,
buffered_callback,
nullptr,
&get_buffer()),
"buffer creation failed");
auto client_thread = rocprofiler_callback_thread_t{};
ROCPROFILER_CALL(rocprofiler_create_callback_thread(&client_thread),
"failure creating callback thread");
ROCPROFILER_CALL(rocprofiler_assign_callback_thread(get_buffer(), client_thread),
"failed to assign thread for buffer");
ROCPROFILER_CALL(rocprofiler_configure_buffered_dispatch_profile_counting_service(
get_client_ctx(), get_buffer(), dispatch_callback, nullptr),
"Could not setup buffered service");
rocprofiler_start_context(get_client_ctx());
// no errors
return 0;
}
void
tool_fini(void*)
{
rocprofiler_flush_buffer(get_buffer());
rocprofiler_stop_context(get_client_ctx());
// Flush buffer isn't waiting....
sleep(2);
std::clog << "In tool fini\n";
auto& cap = *get_capture();
auto wlock = std::unique_lock{cap.m_mutex};
if(cap.captured.size() != cap.expected.size())
{
std::clog << "[ERROR] Expected " << cap.expected.size() << " counters collected but got "
<< cap.captured.size() << "\n";
}
for(const auto& [counter_id, expected] : cap.expected)
{
std::string name = "UNKNOWN";
if(auto pos = cap.expected_counter_names.find(counter_id);
pos != cap.expected_counter_names.end())
{
name = pos->second;
}
std::optional<size_t> actual_size;
if(auto pos = cap.captured.find(counter_id); pos != cap.captured.end())
{
actual_size = pos->second;
}
if(actual_size && *actual_size != expected)
{
std::clog << (*actual_size == expected ? "" : "[ERROR]") << "Counter ID: " << counter_id
<< " (" << name << ")"
<< " expected " << expected << " instances and got " << *actual_size << "\n";
}
else
{
std::clog << "[ERROR] Counter ID: " << counter_id << " (" << name
<< ") is missing from output\n";
}
}
}
} // namespace
extern "C" rocprofiler_tool_configure_result_t*
rocprofiler_configure(uint32_t version,
const char* runtime_version,
uint32_t,
rocprofiler_client_id_t* id)
{
// set the client name
id->name = "CounterClientSample";
// compute major/minor/patch version info
uint32_t major = version / 10000;
uint32_t minor = (version % 10000) / 100;
uint32_t patch = version % 100;
// generate info string
auto info = std::stringstream{};
info << id->name << " is using rocprofiler-sdk v" << major << "." << minor << "." << patch
<< " (" << runtime_version << ")";
std::clog << info.str() << std::endl;
// create configure data
static auto cfg =
rocprofiler_tool_configure_result_t{sizeof(rocprofiler_tool_configure_result_t),
&tool_init,
&tool_fini,
static_cast<void*>(nullptr)};
// return pointer to configure data
return &cfg;
}