ROCpd support [Part 1] (#279)
- Add rocpd support for - cpu_frequency - amd_smi - sampling
Dieser Commit ist enthalten in:
committet von
GitHub
Ursprung
4b4a846b58
Commit
26ae543012
@@ -27,17 +27,22 @@
|
||||
#include "api.hpp"
|
||||
#include "common/setup.hpp"
|
||||
#include "common/static_object.hpp"
|
||||
#include "core/agent.hpp"
|
||||
#include "core/agent_manager.hpp"
|
||||
#include "core/categories.hpp"
|
||||
#include "core/components/fwd.hpp"
|
||||
#include "core/concepts.hpp"
|
||||
#include "core/config.hpp"
|
||||
#include "core/constraint.hpp"
|
||||
#include "core/cpu.hpp"
|
||||
#include "core/debug.hpp"
|
||||
#include "core/defines.hpp"
|
||||
#include "core/dynamic_library.hpp"
|
||||
#include "core/gpu.hpp"
|
||||
#include "core/locking.hpp"
|
||||
#include "core/node_info.hpp"
|
||||
#include "core/perfetto_fwd.hpp"
|
||||
#include "core/rocpd/data_processor.hpp"
|
||||
#include "core/timemory.hpp"
|
||||
#include "core/utility.hpp"
|
||||
#include "library/causal/data.hpp"
|
||||
@@ -77,6 +82,10 @@
|
||||
#include <timemory/utility/join.hpp>
|
||||
#include <timemory/utility/procfs/maps.hpp>
|
||||
|
||||
#if ROCPROFSYS_USE_ROCM > 0
|
||||
# include <rocprofiler-sdk/agent.h>
|
||||
#endif
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <csignal>
|
||||
@@ -86,6 +95,7 @@
|
||||
#include <pthread.h>
|
||||
#include <stdexcept>
|
||||
#include <string_view>
|
||||
#include <unistd.h>
|
||||
#include <utility>
|
||||
|
||||
using namespace rocprofsys;
|
||||
@@ -297,6 +307,66 @@ namespace
|
||||
bool _set_mpi_called = false;
|
||||
std::function<void()> _preinit_callback = []() { get_preinit_bundle()->start(); };
|
||||
|
||||
std::vector<std::string>
|
||||
read_command_line(pid_t _pid)
|
||||
{
|
||||
auto _cmdline = std::vector<std::string>{};
|
||||
auto fcmdline = std::stringstream{};
|
||||
fcmdline << "/proc/" << _pid << "/cmdline";
|
||||
auto ifs = std::ifstream{ fcmdline.str().c_str() };
|
||||
if(ifs)
|
||||
{
|
||||
std::string sarg;
|
||||
while(std::getline(ifs, sarg, '\0'))
|
||||
{
|
||||
_cmdline.push_back(sarg);
|
||||
}
|
||||
ifs.close();
|
||||
}
|
||||
|
||||
return _cmdline;
|
||||
}
|
||||
|
||||
void
|
||||
rocprofsys_preinit_rocpd()
|
||||
{
|
||||
auto& _data_processor = rocpd::data_processor::get_instance();
|
||||
const auto& _n_info = node_info::get_instance();
|
||||
auto _cmd_line = read_command_line(getpid());
|
||||
auto& _agent_manager = agent_manager::get_instance();
|
||||
|
||||
if(_cmd_line.empty())
|
||||
{
|
||||
_cmd_line.emplace_back("rocprofiler-systems");
|
||||
}
|
||||
|
||||
_data_processor.insert_node_info(
|
||||
_n_info.id, _n_info.hash, _n_info.machine_id.c_str(), _n_info.system_name.c_str(),
|
||||
_n_info.node_name.c_str(), _n_info.release.c_str(), _n_info.version.c_str(),
|
||||
_n_info.machine.c_str(), _n_info.domain_name.c_str());
|
||||
_data_processor.insert_process_info(_n_info.id, getppid(), getpid(), 0, 0, 0, 0,
|
||||
_cmd_line[0].c_str(), "{}");
|
||||
|
||||
const auto& agents = _agent_manager.get_agents();
|
||||
for(const auto& rocpd_agent : agents)
|
||||
{
|
||||
auto _base_id = rocpd::data_processor::get_instance().insert_agent(
|
||||
_n_info.id, getpid(),
|
||||
((rocpd_agent->type == agent_type::GPU) ? "GPU" : "CPU"),
|
||||
rocpd_agent->node_id, rocpd_agent->logical_node_id,
|
||||
rocpd_agent->logical_node_type_id, rocpd_agent->id, rocpd_agent->name.c_str(),
|
||||
rocpd_agent->model_name.c_str(), rocpd_agent->vendor_name.c_str(),
|
||||
rocpd_agent->product_name.c_str(), "");
|
||||
rocpd_agent->base_id = _base_id;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rocprofsys_preinit_cpu_agents()
|
||||
{
|
||||
cpu::query_cpu_agents();
|
||||
}
|
||||
|
||||
void
|
||||
rocprofsys_preinit_hidden()
|
||||
{
|
||||
@@ -423,17 +493,17 @@ rocprofsys_init_tooling_hidden(void)
|
||||
{ ROCPROFSYS_DEFAULT_ROCM_PATH }) };
|
||||
#endif
|
||||
|
||||
static bool _once = false;
|
||||
static auto _debug_init = get_debug_init();
|
||||
static pid_t _once = 0;
|
||||
static auto _debug_init = get_debug_init();
|
||||
|
||||
ROCPROFSYS_CONDITIONAL_BASIC_PRINT_F(_debug_init, "State is %s...\n",
|
||||
std::to_string(get_state()).c_str());
|
||||
|
||||
if(get_state() != State::PreInit || get_state() == State::Init || _once)
|
||||
if(get_state() != State::PreInit || get_state() == State::Init || _once == getpid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
_once = true;
|
||||
_once = getpid();
|
||||
|
||||
ROCPROFSYS_SCOPED_THREAD_STATE(ThreadState::Internal);
|
||||
|
||||
@@ -460,6 +530,12 @@ rocprofsys_init_tooling_hidden(void)
|
||||
auto _dtor = scope::destructor{ []() {
|
||||
// if set to finalized, don't continue
|
||||
if(get_state() > State::Active) return;
|
||||
|
||||
#if !(ROCPROFSYS_USE_ROCM > 0)
|
||||
rocprofsys_preinit_cpu_agents();
|
||||
#endif
|
||||
if(get_use_rocpd()) rocprofsys_preinit_rocpd();
|
||||
|
||||
if(get_use_process_sampling())
|
||||
{
|
||||
ROCPROFSYS_SCOPED_SAMPLING_ON_CHILD_THREADS(false);
|
||||
@@ -681,7 +757,6 @@ rocprofsys_finalize_hidden(void)
|
||||
threading::remove_callback(&ensure_initialization);
|
||||
|
||||
bool _is_child = is_child_process();
|
||||
|
||||
set_thread_state(ThreadState::Completed);
|
||||
|
||||
// return if not active
|
||||
@@ -693,6 +768,18 @@ rocprofsys_finalize_hidden(void)
|
||||
}
|
||||
else if(_is_child)
|
||||
{
|
||||
#if defined(ROCPROFSYS_USE_ROCM) && ROCPROFSYS_USE_ROCM > 0
|
||||
// Flush buffered traces in case of child process
|
||||
if(get_use_rocm())
|
||||
{
|
||||
ROCPROFSYS_VERBOSE_F(1, "Shutting down ROCm...\n");
|
||||
rocprofiler_sdk::shutdown();
|
||||
}
|
||||
#endif
|
||||
if(get_use_rocpd())
|
||||
{
|
||||
rocpd::data_processor::get_instance().flush();
|
||||
}
|
||||
set_state(State::Finalized);
|
||||
std::quick_exit(EXIT_SUCCESS);
|
||||
return;
|
||||
@@ -983,6 +1070,10 @@ rocprofsys_finalize_hidden(void)
|
||||
[](int) {});
|
||||
|
||||
common::destroy_static_objects();
|
||||
if(get_use_rocpd())
|
||||
{
|
||||
rocpd::data_processor::get_instance().flush();
|
||||
}
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
@@ -26,18 +26,22 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "core/agent.hpp"
|
||||
#if defined(NDEBUG)
|
||||
# undef NDEBUG
|
||||
#endif
|
||||
|
||||
#include "library/amd_smi.hpp"
|
||||
#include "core/agent_manager.hpp"
|
||||
#include "core/common.hpp"
|
||||
#include "core/components/fwd.hpp"
|
||||
#include "core/config.hpp"
|
||||
#include "core/debug.hpp"
|
||||
#include "core/gpu.hpp"
|
||||
#include "core/node_info.hpp"
|
||||
#include "core/perfetto.hpp"
|
||||
#include "core/rocpd/data_processor.hpp"
|
||||
#include "core/state.hpp"
|
||||
#include "library/amd_smi.hpp"
|
||||
#include "library/runtime.hpp"
|
||||
#include "library/thread_info.hpp"
|
||||
|
||||
@@ -49,13 +53,11 @@
|
||||
#include <timemory/utility/locking.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <chrono>
|
||||
#include <ios>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <sys/resource.h>
|
||||
#include <thread>
|
||||
|
||||
#define ROCPROFSYS_AMD_SMI_CALL(...) \
|
||||
::rocprofsys::amd_smi::check_error(__FILE__, __LINE__, __VA_ARGS__)
|
||||
@@ -69,6 +71,115 @@ using sampler_instances = thread_data<bundle_t, category::amd_smi>;
|
||||
|
||||
namespace
|
||||
{
|
||||
int64_t
|
||||
get_tid()
|
||||
{
|
||||
static thread_local auto _v = threading::get_id();
|
||||
return _v;
|
||||
}
|
||||
|
||||
rocpd::data_processor&
|
||||
get_data_processor()
|
||||
{
|
||||
return rocpd::data_processor::get_instance();
|
||||
}
|
||||
|
||||
void
|
||||
rocpd_initialize_category()
|
||||
{
|
||||
get_data_processor().insert_category(ROCPROFSYS_CATEGORY_AMD_SMI,
|
||||
trait::name<category::amd_smi>::value);
|
||||
}
|
||||
|
||||
void
|
||||
rocpd_initialize_smi_tracks()
|
||||
{
|
||||
auto& data_processor = get_data_processor();
|
||||
auto& n_info = node_info::get_instance();
|
||||
const auto thread_id = std::nullopt; // Internal thread ID for amd-smi
|
||||
|
||||
data_processor.insert_track(trait::name<category::amd_smi_mm_busy>::value, n_info.id,
|
||||
getpid(), thread_id);
|
||||
data_processor.insert_track(trait::name<category::amd_smi_power>::value, n_info.id,
|
||||
getpid(), thread_id);
|
||||
data_processor.insert_track(trait::name<category::amd_smi_temp>::value, n_info.id,
|
||||
getpid(), thread_id);
|
||||
data_processor.insert_track(trait::name<category::amd_smi_memory_usage>::value,
|
||||
n_info.id, getpid(), thread_id);
|
||||
}
|
||||
|
||||
void
|
||||
rocpd_initialize_smi_pmc(size_t gpu_id)
|
||||
{
|
||||
auto& data_processor = get_data_processor();
|
||||
// find the proper values for a following definitions
|
||||
size_t EVENT_CODE = 0;
|
||||
size_t INSTANCE_ID = 0;
|
||||
const char* LONG_DESCRIPTION = "";
|
||||
const char* COMPONENT = "";
|
||||
const char* BLOCK = "";
|
||||
const char* EXPRESSION = "";
|
||||
const char* CELSIUS_DEGREES = "\u00B0C";
|
||||
auto ni = node_info::get_instance();
|
||||
const auto* TARGET_ARCH = "GPU";
|
||||
|
||||
auto& _agent_manager = agent_manager::get_instance();
|
||||
auto base_id = _agent_manager.get_agent_by_id(gpu_id, agent_type::GPU).base_id;
|
||||
|
||||
data_processor.insert_pmc_description(
|
||||
ni.id, getpid(), base_id, TARGET_ARCH, EVENT_CODE, INSTANCE_ID,
|
||||
trait::name<category::amd_smi_mm_busy>::value, "Busy",
|
||||
trait::name<category::amd_smi_mm_busy>::description, LONG_DESCRIPTION, COMPONENT,
|
||||
"%", "ABS", BLOCK, EXPRESSION, 0, 0);
|
||||
|
||||
data_processor.insert_pmc_description(
|
||||
ni.id, getpid(), base_id, TARGET_ARCH, EVENT_CODE, INSTANCE_ID,
|
||||
trait::name<category::amd_smi_temp>::value, "Temp",
|
||||
trait::name<category::amd_smi_temp>::description, LONG_DESCRIPTION, COMPONENT,
|
||||
CELSIUS_DEGREES, "ABS", BLOCK, EXPRESSION, 0, 0);
|
||||
|
||||
data_processor.insert_pmc_description(
|
||||
ni.id, getpid(), base_id, TARGET_ARCH, EVENT_CODE, INSTANCE_ID,
|
||||
trait::name<category::amd_smi_power>::value, "Pow",
|
||||
trait::name<category::amd_smi_power>::description, LONG_DESCRIPTION, COMPONENT,
|
||||
"w", "ABS", BLOCK, EXPRESSION, 0, 0);
|
||||
|
||||
data_processor.insert_pmc_description(
|
||||
ni.id, getpid(), base_id, TARGET_ARCH, EVENT_CODE, INSTANCE_ID,
|
||||
trait::name<category::amd_smi_memory_usage>::value, "MemUsg",
|
||||
trait::name<category::amd_smi_memory_usage>::description, LONG_DESCRIPTION,
|
||||
COMPONENT, "MB", "ABS", BLOCK, EXPRESSION, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
rocpd_process_smi_pmc_events(const uint32_t device_id, const amd_smi::settings& settings,
|
||||
uint64_t timestamp, double busy, double temp, double power,
|
||||
double usage)
|
||||
{
|
||||
if(!(settings.busy || settings.temp || settings.power || settings.mem_usage)) return;
|
||||
|
||||
auto& data_processor = get_data_processor();
|
||||
auto event_id = data_processor.insert_event(ROCPROFSYS_CATEGORY_AMD_SMI, 0, 0, 0);
|
||||
|
||||
auto& _agent_manager = agent_manager::get_instance();
|
||||
auto base_id = _agent_manager.get_agent_by_id(device_id, agent_type::GPU).base_id;
|
||||
|
||||
auto insert_event_and_sample = [&](bool enabled, const char* name, double value) {
|
||||
if(!enabled) return;
|
||||
data_processor.insert_pmc_event(event_id, base_id, name, value);
|
||||
data_processor.insert_sample(name, timestamp, event_id);
|
||||
};
|
||||
|
||||
insert_event_and_sample(settings.busy, trait::name<category::amd_smi_mm_busy>::value,
|
||||
busy);
|
||||
insert_event_and_sample(settings.temp, trait::name<category::amd_smi_temp>::value,
|
||||
temp);
|
||||
insert_event_and_sample(settings.power, trait::name<category::amd_smi_power>::value,
|
||||
power);
|
||||
insert_event_and_sample(settings.mem_usage,
|
||||
trait::name<category::amd_smi_memory_usage>::value, usage);
|
||||
}
|
||||
|
||||
auto&
|
||||
get_settings(uint32_t _dev_id)
|
||||
{
|
||||
@@ -140,6 +251,8 @@ data::data(uint32_t _dev_id) { sample(_dev_id); }
|
||||
void
|
||||
data::sample(uint32_t _dev_id)
|
||||
{
|
||||
if(is_child_process()) return;
|
||||
|
||||
auto _ts = tim::get_clock_real_now<size_t, std::nano>();
|
||||
assert(_ts < std::numeric_limits<int64_t>::max());
|
||||
amdsmi_gpu_metrics_t _gpu_metrics;
|
||||
@@ -168,7 +281,6 @@ data::sample(uint32_t _dev_id)
|
||||
}
|
||||
|
||||
amdsmi_processor_handle sample_handle = gpu::get_handle_from_id(_dev_id);
|
||||
|
||||
ROCPROFSYS_AMDSMI_GET(get_settings(m_dev_id).busy, amdsmi_get_gpu_activity,
|
||||
sample_handle, &m_busy_perc);
|
||||
ROCPROFSYS_AMDSMI_GET(get_settings(m_dev_id).temp, amdsmi_get_temp_metric,
|
||||
@@ -276,10 +388,15 @@ config()
|
||||
*_bundle_data.at(i) = unique_ptr_t<bundle_t>{ new bundle_t{} };
|
||||
}
|
||||
}
|
||||
|
||||
data::get_initial().resize(data::device_count);
|
||||
for(auto itr : data::device_list)
|
||||
data::get_initial().at(itr).sample(itr);
|
||||
|
||||
if(get_use_rocpd())
|
||||
{
|
||||
rocpd_initialize_category();
|
||||
rocpd_initialize_smi_tracks();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -363,192 +480,194 @@ data::post_process(uint32_t _dev_id)
|
||||
|
||||
auto _settings = get_settings(_dev_id);
|
||||
|
||||
auto _process_perfetto = [&]() {
|
||||
constexpr uint8_t AMD_SMI_METRICS_COUNT = 8;
|
||||
auto _idx = std::array<uint64_t, AMD_SMI_METRICS_COUNT>{};
|
||||
auto use_perfetto = get_use_perfetto();
|
||||
auto use_rocpd = get_use_rocpd();
|
||||
|
||||
if(use_rocpd)
|
||||
{
|
||||
rocpd_initialize_smi_pmc(_dev_id);
|
||||
}
|
||||
|
||||
for(auto& itr : _amd_smi)
|
||||
{
|
||||
using counter_track = perfetto_counter_track<data>;
|
||||
if(itr.m_dev_id != _dev_id) continue;
|
||||
|
||||
uint64_t _ts = itr.m_ts;
|
||||
if(!_thread_info->is_valid_time(_ts)) continue;
|
||||
|
||||
double _gfxbusy = itr.m_busy_perc.gfx_activity;
|
||||
double _umcbusy = itr.m_busy_perc.umc_activity;
|
||||
double _mmbusy = itr.m_busy_perc.mm_activity;
|
||||
double _temp = itr.m_temp;
|
||||
double _power = itr.m_power.current_socket_power;
|
||||
double _usage = itr.m_mem_usage / static_cast<double>(units::megabyte);
|
||||
|
||||
auto setup_perfetto_counter_tracks = [&]() {
|
||||
if(counter_track::exists(_dev_id)) return;
|
||||
|
||||
auto addendum = [&](const char* _v) {
|
||||
return JOIN(" ", "GPU", _v, JOIN("", '[', _dev_id, ']'), "(S)");
|
||||
};
|
||||
|
||||
auto addendum_blk = [&](std::size_t _i, const char* _metric,
|
||||
std::size_t xcp_idx = SIZE_MAX) {
|
||||
if(xcp_idx != SIZE_MAX)
|
||||
{
|
||||
return JOIN(
|
||||
" ", "GPU", JOIN("", '[', _dev_id, ']'), _metric,
|
||||
JOIN("", "XCP_", xcp_idx, ": [", (_i < 10 ? "0" : ""), _i, ']'),
|
||||
"(S)");
|
||||
}
|
||||
else
|
||||
{
|
||||
return JOIN(" ", "GPU", JOIN("", '[', _dev_id, ']'), _metric,
|
||||
JOIN("", "[", (_i < 10 ? "0" : ""), _i, ']'), "(S)");
|
||||
}
|
||||
};
|
||||
|
||||
{
|
||||
_idx.fill(_idx.size());
|
||||
uint64_t nidx = 0;
|
||||
if(_settings.busy)
|
||||
{
|
||||
_idx.at(0) = nidx++; // GFX Busy
|
||||
_idx.at(1) = nidx++; // UMC Busy
|
||||
_idx.at(2) = nidx++; // MM Busy
|
||||
counter_track::emplace(_dev_id, addendum("GFX Busy"), "%");
|
||||
counter_track::emplace(_dev_id, addendum("UMC Busy"), "%");
|
||||
counter_track::emplace(_dev_id, addendum("MM Busy"), "%");
|
||||
}
|
||||
if(_settings.temp) _idx.at(3) = nidx++;
|
||||
if(_settings.power) _idx.at(4) = nidx++;
|
||||
if(_settings.mem_usage) _idx.at(5) = nidx++;
|
||||
if(_settings.vcn_activity) _idx.at(6) = nidx++;
|
||||
if(_settings.jpeg_activity) _idx.at(7) = nidx++;
|
||||
}
|
||||
|
||||
for(auto& itr : _amd_smi)
|
||||
{
|
||||
using counter_track = perfetto_counter_track<data>;
|
||||
if(itr.m_dev_id != _dev_id) continue;
|
||||
if(!counter_track::exists(_dev_id))
|
||||
if(_settings.temp)
|
||||
{
|
||||
auto addendum = [&](const char* _v) {
|
||||
return JOIN(" ", "GPU", _v, JOIN("", '[', _dev_id, ']'), "(S)");
|
||||
};
|
||||
auto addendum_blk = [&](std::size_t _i, const char* _metric,
|
||||
std::size_t xcp_idx = SIZE_MAX) {
|
||||
if(xcp_idx != SIZE_MAX)
|
||||
{
|
||||
return JOIN(" ", "GPU", JOIN("", '[', _dev_id, ']'), _metric,
|
||||
JOIN("", "XCP_", xcp_idx, ": [", (_i < 10 ? "0" : ""),
|
||||
_i, ']'),
|
||||
"(S)");
|
||||
}
|
||||
else
|
||||
{
|
||||
return JOIN(" ", "GPU", JOIN("", '[', _dev_id, ']'), _metric,
|
||||
JOIN("", "[", (_i < 10 ? "0" : ""), _i, ']'), "(S)");
|
||||
}
|
||||
};
|
||||
|
||||
if(_settings.busy)
|
||||
counter_track::emplace(_dev_id, addendum("Temperature"), "deg C");
|
||||
}
|
||||
if(_settings.power)
|
||||
{
|
||||
counter_track::emplace(_dev_id, addendum("Current Power"), "watts");
|
||||
}
|
||||
if(_settings.mem_usage)
|
||||
{
|
||||
counter_track::emplace(_dev_id, addendum("Memory Usage"), "megabytes");
|
||||
}
|
||||
if(_settings.vcn_activity)
|
||||
{
|
||||
if(itr.m_xcp_metrics.empty())
|
||||
{
|
||||
counter_track::emplace(_dev_id, addendum("GFX Busy"), "%");
|
||||
counter_track::emplace(_dev_id, addendum("UMC Busy"), "%");
|
||||
counter_track::emplace(_dev_id, addendum("MM Busy"), "%");
|
||||
ROCPROFSYS_VERBOSE(
|
||||
1, "No VCN activity data collected from device %u\n", _dev_id);
|
||||
}
|
||||
if(_settings.temp)
|
||||
counter_track::emplace(_dev_id, addendum("Temperature"), "deg C");
|
||||
if(_settings.power)
|
||||
counter_track::emplace(_dev_id, addendum("Current Power"), "watts");
|
||||
if(_settings.mem_usage)
|
||||
counter_track::emplace(_dev_id, addendum("Memory Usage"),
|
||||
"megabytes");
|
||||
if(_settings.vcn_activity)
|
||||
else if(gpu::is_vcn_activity_supported(_dev_id))
|
||||
{
|
||||
if(itr.m_xcp_metrics.empty())
|
||||
{
|
||||
ROCPROFSYS_VERBOSE(
|
||||
1, "No VCN activity data collected from device %u\n",
|
||||
_dev_id);
|
||||
}
|
||||
else if(gpu::is_vcn_activity_supported(_dev_id))
|
||||
{
|
||||
// For VCN activity, use simple indexing
|
||||
for(std::size_t i = 0;
|
||||
i < std::size(itr.m_xcp_metrics[0].vcn_busy); ++i)
|
||||
counter_track::emplace(_dev_id,
|
||||
addendum_blk(i, "VCN Activity"), "%");
|
||||
}
|
||||
else
|
||||
{
|
||||
for(std::size_t xcp = 0; xcp < std::size(itr.m_xcp_metrics);
|
||||
++xcp)
|
||||
{
|
||||
for(std::size_t i = 0;
|
||||
i < std::size(itr.m_xcp_metrics[xcp].vcn_busy); ++i)
|
||||
{
|
||||
counter_track::emplace(
|
||||
_dev_id, addendum_blk(i, "VCN Activity", xcp), "%");
|
||||
}
|
||||
}
|
||||
}
|
||||
// For VCN activity, use simple indexing
|
||||
for(std::size_t i = 0; i < std::size(itr.m_xcp_metrics[0].vcn_busy);
|
||||
++i)
|
||||
counter_track::emplace(_dev_id, addendum_blk(i, "VCN Activity"),
|
||||
"%");
|
||||
}
|
||||
if(_settings.jpeg_activity)
|
||||
else
|
||||
{
|
||||
if(itr.m_xcp_metrics.empty())
|
||||
for(std::size_t xcp = 0; xcp < std::size(itr.m_xcp_metrics); ++xcp)
|
||||
{
|
||||
ROCPROFSYS_VERBOSE(
|
||||
1, "No JPEG activity data collected from device %u\n",
|
||||
_dev_id);
|
||||
}
|
||||
else if(gpu::is_jpeg_activity_supported(_dev_id))
|
||||
{
|
||||
// For JPEG activity, use simple indexing
|
||||
for(std::size_t i = 0;
|
||||
i < std::size(itr.m_xcp_metrics[0].jpeg_busy); ++i)
|
||||
counter_track::emplace(_dev_id,
|
||||
addendum_blk(i, "JPEG Activity"), "%");
|
||||
}
|
||||
else
|
||||
{
|
||||
for(std::size_t xcp = 0; xcp < std::size(itr.m_xcp_metrics);
|
||||
++xcp)
|
||||
i < std::size(itr.m_xcp_metrics[xcp].vcn_busy); ++i)
|
||||
{
|
||||
for(std::size_t i = 0;
|
||||
i < std::size(itr.m_xcp_metrics[xcp].jpeg_busy); ++i)
|
||||
counter_track::emplace(
|
||||
_dev_id, addendum_blk(i, "JPEG Activity", xcp), "%");
|
||||
counter_track::emplace(
|
||||
_dev_id, addendum_blk(i, "VCN Activity", xcp), "%");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
uint64_t _ts = itr.m_ts;
|
||||
if(!_thread_info->is_valid_time(_ts)) continue;
|
||||
if(_settings.jpeg_activity)
|
||||
{
|
||||
if(itr.m_xcp_metrics.empty())
|
||||
{
|
||||
ROCPROFSYS_VERBOSE(
|
||||
1, "No JPEG activity data collected from device %u\n", _dev_id);
|
||||
}
|
||||
else if(gpu::is_jpeg_activity_supported(_dev_id))
|
||||
{
|
||||
for(std::size_t i = 0; i < std::size(itr.m_xcp_metrics[0].jpeg_busy);
|
||||
++i)
|
||||
counter_track::emplace(_dev_id, addendum_blk(i, "JPEG Activity"),
|
||||
"%");
|
||||
}
|
||||
else
|
||||
{
|
||||
for(std::size_t xcp = 0; xcp < std::size(itr.m_xcp_metrics); ++xcp)
|
||||
{
|
||||
for(std::size_t i = 0;
|
||||
i < std::size(itr.m_xcp_metrics[xcp].jpeg_busy); ++i)
|
||||
counter_track::emplace(
|
||||
_dev_id, addendum_blk(i, "JPEG Activity", xcp), "%");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
double _gfxbusy = itr.m_busy_perc.gfx_activity;
|
||||
double _umcbusy = itr.m_busy_perc.umc_activity;
|
||||
double _mmbusy = itr.m_busy_perc.mm_activity;
|
||||
double _temp = itr.m_temp;
|
||||
double _power = itr.m_power.current_socket_power;
|
||||
double _usage = itr.m_mem_usage / static_cast<double>(units::megabyte);
|
||||
auto write_perfetto_metrics = [&]() {
|
||||
size_t track_index = 0;
|
||||
|
||||
if(_settings.busy)
|
||||
{
|
||||
TRACE_COUNTER("device_busy_gfx", counter_track::at(_dev_id, _idx.at(0)),
|
||||
_ts, _gfxbusy);
|
||||
TRACE_COUNTER("device_busy_umc", counter_track::at(_dev_id, _idx.at(1)),
|
||||
_ts, _umcbusy);
|
||||
TRACE_COUNTER("device_busy_mm", counter_track::at(_dev_id, _idx.at(2)),
|
||||
TRACE_COUNTER("device_busy_gfx",
|
||||
counter_track::at(_dev_id, track_index++), _ts, _gfxbusy);
|
||||
TRACE_COUNTER("device_busy_umc",
|
||||
counter_track::at(_dev_id, track_index++), _ts, _umcbusy);
|
||||
TRACE_COUNTER("device_busy_mm", counter_track::at(_dev_id, track_index++),
|
||||
_ts, _mmbusy);
|
||||
}
|
||||
if(_settings.temp)
|
||||
TRACE_COUNTER("device_temp", counter_track::at(_dev_id, _idx.at(3)), _ts,
|
||||
_temp);
|
||||
{
|
||||
TRACE_COUNTER("device_temp", counter_track::at(_dev_id, track_index++),
|
||||
_ts, _temp);
|
||||
}
|
||||
if(_settings.power)
|
||||
TRACE_COUNTER("device_power", counter_track::at(_dev_id, _idx.at(4)), _ts,
|
||||
_power);
|
||||
{
|
||||
TRACE_COUNTER("device_power", counter_track::at(_dev_id, track_index++),
|
||||
_ts, _power);
|
||||
}
|
||||
if(_settings.mem_usage)
|
||||
{
|
||||
TRACE_COUNTER("device_memory_usage",
|
||||
counter_track::at(_dev_id, _idx.at(5)), _ts, _usage);
|
||||
counter_track::at(_dev_id, track_index++), _ts, _usage);
|
||||
}
|
||||
|
||||
if(_settings.vcn_activity && !itr.m_xcp_metrics.empty())
|
||||
{
|
||||
uint64_t idx = _idx.at(6);
|
||||
// Iterate over all XCPs and their VCN busy/activity values
|
||||
for(const auto& metrics : itr.m_xcp_metrics)
|
||||
{
|
||||
for(const auto& vcn_val : metrics.vcn_busy)
|
||||
{
|
||||
TRACE_COUNTER("device_vcn_activity",
|
||||
counter_track::at(_dev_id, idx), _ts, vcn_val);
|
||||
++idx;
|
||||
counter_track::at(_dev_id, track_index++), _ts,
|
||||
vcn_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(_settings.jpeg_activity && !itr.m_xcp_metrics.empty())
|
||||
{
|
||||
uint64_t idx = _idx.at(7);
|
||||
// Calculate total VCN metrics to properly offset JPEG metrics index
|
||||
if(_settings.vcn_activity)
|
||||
{
|
||||
size_t total_vcn_metrics = 0;
|
||||
for(const auto& metrics : itr.m_xcp_metrics)
|
||||
total_vcn_metrics += metrics.vcn_busy.size();
|
||||
if(total_vcn_metrics > 0) idx += (total_vcn_metrics - 1);
|
||||
}
|
||||
// Iterate over all XCPs and their JPEG busy/activity values
|
||||
for(const auto& metrics : itr.m_xcp_metrics)
|
||||
{
|
||||
for(const auto& jpeg_val : metrics.jpeg_busy)
|
||||
{
|
||||
TRACE_COUNTER("device_jpeg_activity",
|
||||
counter_track::at(_dev_id, idx), _ts, jpeg_val);
|
||||
++idx;
|
||||
counter_track::at(_dev_id, track_index++), _ts,
|
||||
jpeg_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
if(get_use_perfetto()) _process_perfetto();
|
||||
if(use_perfetto)
|
||||
{
|
||||
setup_perfetto_counter_tracks();
|
||||
write_perfetto_metrics();
|
||||
}
|
||||
|
||||
if(use_rocpd)
|
||||
{
|
||||
rocpd_process_smi_pmc_events(_dev_id, _settings, _ts, _mmbusy, _temp, _power,
|
||||
_usage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
@@ -573,7 +692,7 @@ setup()
|
||||
ROCPROFSYS_VERBOSE_F(0, "AMD SMI version: %u.%u.%u - str: %s.\n", _version.major,
|
||||
_version.minor, _version.release, _version.build);
|
||||
|
||||
data::device_count = gpu::get_processor_count();
|
||||
data::device_count = gpu::device_count();
|
||||
|
||||
auto _devices_v = get_sampling_gpus();
|
||||
for(auto& itr : _devices_v)
|
||||
@@ -668,7 +787,6 @@ setup()
|
||||
}
|
||||
|
||||
is_initialized() = true;
|
||||
|
||||
data::setup();
|
||||
} catch(std::runtime_error& _e)
|
||||
{
|
||||
@@ -705,7 +823,10 @@ void
|
||||
post_process()
|
||||
{
|
||||
for(auto itr : data::device_list)
|
||||
{
|
||||
ROCPROFSYS_VERBOSE(2, "Post-processing amd-smi data for device: %d", itr);
|
||||
data::post_process(itr);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
||||
@@ -21,10 +21,14 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#include "library/components/backtrace_metrics.hpp"
|
||||
#include "core/agent.hpp"
|
||||
#include "core/agent_manager.hpp"
|
||||
#include "core/components/fwd.hpp"
|
||||
#include "core/config.hpp"
|
||||
#include "core/debug.hpp"
|
||||
#include "core/node_info.hpp"
|
||||
#include "core/perfetto.hpp"
|
||||
#include "core/rocpd/data_processor.hpp"
|
||||
#include "library/components/ensure_storage.hpp"
|
||||
#include "library/ptl.hpp"
|
||||
#include "library/runtime.hpp"
|
||||
@@ -137,6 +141,12 @@ backtrace_metrics::get_hw_counter_labels(int64_t _tid)
|
||||
return (_v) ? *_v : std::vector<std::string>{};
|
||||
}
|
||||
|
||||
rocpd::data_processor&
|
||||
get_data_processor()
|
||||
{
|
||||
return rocpd::data_processor::get_instance();
|
||||
}
|
||||
|
||||
void
|
||||
backtrace_metrics::start()
|
||||
{}
|
||||
@@ -327,6 +337,228 @@ backtrace_metrics::fini_perfetto(int64_t _tid, valid_array_t _valid)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rocpd_init_categories()
|
||||
{
|
||||
static bool _is_initialized = false;
|
||||
if(_is_initialized) return;
|
||||
|
||||
get_data_processor().insert_category(
|
||||
category_enum_id<category::thread_cpu_time>::value,
|
||||
trait::name<category::thread_cpu_time>::value);
|
||||
get_data_processor().insert_category(
|
||||
category_enum_id<category::thread_peak_memory>::value,
|
||||
trait::name<category::thread_peak_memory>::value);
|
||||
get_data_processor().insert_category(
|
||||
category_enum_id<category::thread_context_switch>::value,
|
||||
trait::name<category::thread_context_switch>::value);
|
||||
get_data_processor().insert_category(
|
||||
category_enum_id<category::thread_page_fault>::value,
|
||||
trait::name<category::thread_page_fault>::value);
|
||||
get_data_processor().insert_category(
|
||||
category_enum_id<category::thread_hardware_counter>::value,
|
||||
trait::name<category::thread_hardware_counter>::value);
|
||||
|
||||
_is_initialized = true;
|
||||
}
|
||||
|
||||
template <typename Category>
|
||||
void
|
||||
rocpd_init_tracks(int64_t _tid)
|
||||
{
|
||||
auto& data_processor = get_data_processor();
|
||||
auto& n_info = node_info::get_instance();
|
||||
const auto& t_info = thread_info::get(_tid, SequentTID);
|
||||
auto _tid_name = JOIN("", '[', _tid, ']');
|
||||
|
||||
auto thread_idx = data_processor.insert_thread_info(
|
||||
n_info.id, getppid(), getpid(), t_info->index_data->system_value,
|
||||
JOIN(" ", "Thread", _tid).c_str(), t_info->get_start(), t_info->get_stop(), "{}");
|
||||
|
||||
if constexpr(std::is_same_v<Category, category::thread_hardware_counter>)
|
||||
{
|
||||
// Initialize hw_counter_tracks and create one track for each hardware counter
|
||||
auto _hw_cnt_labels = *get_papi_labels(_tid);
|
||||
for(auto& itr : _hw_cnt_labels)
|
||||
{
|
||||
std::string _desc = tim::papi::get_event_info(itr).short_descr;
|
||||
if(_desc.empty()) _desc = itr;
|
||||
ROCPROFSYS_CI_THROW(_desc.empty(), "Empty description for %s\n", itr.c_str());
|
||||
|
||||
std::string track_name = JOIN(' ', "Thread", _desc, _tid_name, "(S)");
|
||||
data_processor.insert_track(track_name.c_str(), n_info.id, getpid(),
|
||||
thread_idx, "{}");
|
||||
}
|
||||
}
|
||||
else
|
||||
data_processor.insert_track(
|
||||
JOIN('_', trait::name<Category>::value, _tid_name).c_str(), n_info.id,
|
||||
getpid(), thread_idx, "{}");
|
||||
}
|
||||
|
||||
template <typename Category>
|
||||
void
|
||||
rocpd_initialize_backtrace_metrics_pmc(size_t dev_id, const char* units, int64_t _tid)
|
||||
{
|
||||
auto& data_processor = get_data_processor();
|
||||
auto _tid_name = JOIN("", '[', _tid, ']');
|
||||
|
||||
size_t EVENT_CODE = 0;
|
||||
size_t INSTANCE_ID = 0;
|
||||
const char* LONG_DESCRIPTION = "";
|
||||
const char* COMPONENT = "";
|
||||
const char* BLOCK = "";
|
||||
const char* EXPRESSION = "";
|
||||
auto ni = node_info::get_instance();
|
||||
const auto* TARGET_ARCH = "CPU";
|
||||
|
||||
auto& _agent_manager = agent_manager::get_instance();
|
||||
auto _base_id = _agent_manager.get_agent_by_id(dev_id, agent_type::CPU).base_id;
|
||||
|
||||
if constexpr(std::is_same_v<Category, category::thread_hardware_counter>)
|
||||
{
|
||||
auto _hw_cnt_labels = *get_papi_labels(_tid);
|
||||
for(auto& itr : _hw_cnt_labels)
|
||||
{
|
||||
std::string _desc = tim::papi::get_event_info(itr).short_descr;
|
||||
if(_desc.empty()) _desc = itr;
|
||||
ROCPROFSYS_CI_THROW(_desc.empty(), "Empty description for %s\n", itr.c_str());
|
||||
|
||||
std::string track_name = JOIN(' ', "Thread", _desc, _tid_name, "(S)");
|
||||
|
||||
data_processor.insert_pmc_description(
|
||||
ni.id, getpid(), _base_id, TARGET_ARCH, EVENT_CODE, INSTANCE_ID,
|
||||
track_name.c_str(), trait::name<Category>::value,
|
||||
trait::name<Category>::description, LONG_DESCRIPTION, COMPONENT, units,
|
||||
"ABS", BLOCK, EXPRESSION, 0, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
data_processor.insert_pmc_description(
|
||||
ni.id, getpid(), _base_id, TARGET_ARCH, EVENT_CODE, INSTANCE_ID,
|
||||
JOIN("_", trait::name<Category>::value, _tid_name).c_str(),
|
||||
trait::name<Category>::value, trait::name<Category>::description,
|
||||
LONG_DESCRIPTION, COMPONENT, units, "ABS", BLOCK, EXPRESSION, 0, 0);
|
||||
}
|
||||
|
||||
template <typename Category, typename Value>
|
||||
void
|
||||
rocpd_process_backtrace_metrics_events(const uint32_t device_id, uint64_t timestamp,
|
||||
Value value, int64_t _tid)
|
||||
{
|
||||
auto& data_processor = get_data_processor();
|
||||
auto _tid_name = JOIN("", '[', _tid, ']');
|
||||
auto event_id =
|
||||
data_processor.insert_event(category_enum_id<Category>::value, 0, 0, 0);
|
||||
auto& agent_mngr = agent_manager::get_instance();
|
||||
auto base_id = agent_mngr.get_agent_by_id(device_id, agent_type::CPU).base_id;
|
||||
|
||||
auto insert_event_and_sample = [&](const char* name, double _value) {
|
||||
data_processor.insert_pmc_event(event_id, base_id, name, _value);
|
||||
data_processor.insert_sample(name, timestamp, event_id);
|
||||
};
|
||||
|
||||
if constexpr(std::is_same_v<Category, category::thread_hardware_counter>)
|
||||
{
|
||||
auto _hw_cnt_labels = *get_papi_labels(_tid);
|
||||
const auto& _hw_counters =
|
||||
static_cast<backtrace_metrics::hw_counter_data_t>(value);
|
||||
for(size_t i = 0; i < _hw_cnt_labels.size() && i < _hw_counters.size(); ++i)
|
||||
{
|
||||
std::string _desc = tim::papi::get_event_info(_hw_cnt_labels[i]).short_descr;
|
||||
if(_desc.empty()) _desc = _hw_cnt_labels[i];
|
||||
std::string track_name = JOIN(' ', "Thread", _desc, _tid_name, "(S)");
|
||||
|
||||
insert_event_and_sample(track_name.c_str(), _hw_counters.at(i));
|
||||
}
|
||||
}
|
||||
else
|
||||
insert_event_and_sample(
|
||||
JOIN("_", trait::name<Category>::value, _tid_name).c_str(), value);
|
||||
}
|
||||
|
||||
void
|
||||
backtrace_metrics::init_rocpd(int64_t _tid, valid_array_t _valid)
|
||||
{
|
||||
rocpd_init_categories();
|
||||
if(get_valid(category::thread_cpu_time{}, _valid))
|
||||
{
|
||||
rocpd_init_tracks<category::thread_cpu_time>(_tid);
|
||||
rocpd_initialize_backtrace_metrics_pmc<category::thread_cpu_time>(0, "sec", _tid);
|
||||
}
|
||||
if(get_valid(category::thread_peak_memory{}, _valid))
|
||||
{
|
||||
rocpd_init_tracks<category::thread_peak_memory>(_tid);
|
||||
rocpd_initialize_backtrace_metrics_pmc<category::thread_peak_memory>(0, "MB",
|
||||
_tid);
|
||||
}
|
||||
if(get_valid(category::thread_context_switch{}, _valid))
|
||||
{
|
||||
rocpd_init_tracks<category::thread_context_switch>(_tid);
|
||||
rocpd_initialize_backtrace_metrics_pmc<category::thread_context_switch>(0, "",
|
||||
_tid);
|
||||
}
|
||||
if(get_valid(category::thread_page_fault{}, _valid))
|
||||
{
|
||||
rocpd_init_tracks<category::thread_page_fault>(_tid);
|
||||
rocpd_initialize_backtrace_metrics_pmc<category::thread_page_fault>(0, "", _tid);
|
||||
}
|
||||
if(get_valid(type_list<hw_counters>{}, _valid) &&
|
||||
get_valid(category::thread_hardware_counter{}, _valid))
|
||||
{
|
||||
rocpd_init_tracks<category::thread_hardware_counter>(_tid);
|
||||
rocpd_initialize_backtrace_metrics_pmc<category::thread_hardware_counter>(0, "",
|
||||
_tid);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
backtrace_metrics::fini_rocpd(int64_t _tid, valid_array_t _valid)
|
||||
{
|
||||
const auto& _thread_info = thread_info::get(_tid, SequentTID);
|
||||
|
||||
ROCPROFSYS_CI_THROW(!_thread_info, "Error! missing thread info for tid=%li\n", _tid);
|
||||
if(!_thread_info) return;
|
||||
|
||||
uint64_t _ts = _thread_info->get_stop();
|
||||
|
||||
if(get_valid(category::thread_cpu_time{}, _valid))
|
||||
{
|
||||
rocpd_process_backtrace_metrics_events<category::thread_cpu_time, double>(
|
||||
0, _ts, 0, _tid);
|
||||
}
|
||||
|
||||
if(get_valid(category::thread_peak_memory{}, _valid))
|
||||
{
|
||||
rocpd_process_backtrace_metrics_events<category::thread_peak_memory, double>(
|
||||
0, _ts, 0, _tid);
|
||||
}
|
||||
|
||||
if(get_valid(category::thread_context_switch{}, _valid))
|
||||
{
|
||||
rocpd_process_backtrace_metrics_events<category::thread_context_switch, int64_t>(
|
||||
0, _ts, 0, _tid);
|
||||
}
|
||||
|
||||
if(get_valid(category::thread_page_fault{}, _valid))
|
||||
{
|
||||
rocpd_process_backtrace_metrics_events<category::thread_page_fault, int64_t>(
|
||||
0, _ts, 0, _tid);
|
||||
}
|
||||
|
||||
if(get_valid(type_list<hw_counters>{}, _valid) &&
|
||||
get_valid(category::thread_hardware_counter{}, _valid))
|
||||
{
|
||||
auto _hw_cnt_labels = *get_papi_labels(_tid);
|
||||
hw_counter_data_t zero_counters{};
|
||||
zero_counters.fill(0.0);
|
||||
|
||||
rocpd_process_backtrace_metrics_events<category::thread_hardware_counter,
|
||||
hw_counter_data_t>(0, _ts, zero_counters,
|
||||
_tid);
|
||||
}
|
||||
}
|
||||
|
||||
backtrace_metrics&
|
||||
backtrace_metrics::operator-=(const backtrace_metrics& _rhs)
|
||||
{
|
||||
@@ -407,6 +639,43 @@ backtrace_metrics::post_process_perfetto(int64_t _tid, uint64_t _ts) const
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
backtrace_metrics::post_process_rocpd(int64_t _tid, uint64_t _ts) const
|
||||
{
|
||||
auto is_category_enabled = [&](const auto& _category) { return (*this)(_category); };
|
||||
|
||||
if(is_category_enabled(category::thread_cpu_time{}))
|
||||
{
|
||||
rocpd_process_backtrace_metrics_events<category::thread_cpu_time, double>(
|
||||
0, _ts, m_cpu / units::sec, _tid);
|
||||
}
|
||||
|
||||
if(is_category_enabled(category::thread_peak_memory{}))
|
||||
{
|
||||
rocpd_process_backtrace_metrics_events<category::thread_peak_memory, double>(
|
||||
0, _ts, m_mem_peak / units::megabyte, _tid);
|
||||
}
|
||||
|
||||
if(is_category_enabled(category::thread_context_switch{}))
|
||||
{
|
||||
rocpd_process_backtrace_metrics_events<category::thread_context_switch, int64_t>(
|
||||
0, _ts, m_ctx_swch, _tid);
|
||||
}
|
||||
|
||||
if(is_category_enabled(category::thread_page_fault{}))
|
||||
{
|
||||
rocpd_process_backtrace_metrics_events<category::thread_page_fault, int64_t>(
|
||||
0, _ts, m_page_flt, _tid);
|
||||
}
|
||||
if(is_category_enabled(type_list<hw_counters>{}) &&
|
||||
is_category_enabled(category::thread_hardware_counter{}))
|
||||
{
|
||||
rocpd_process_backtrace_metrics_events<category::thread_hardware_counter,
|
||||
hw_counter_data_t>(0, _ts, m_hw_counter,
|
||||
_tid);
|
||||
}
|
||||
}
|
||||
} // namespace component
|
||||
} // namespace rocprofsys
|
||||
|
||||
|
||||
@@ -83,6 +83,8 @@ struct backtrace_metrics : comp::empty_base
|
||||
static void configure(bool, int64_t _tid = threading::get_id());
|
||||
static void init_perfetto(int64_t _tid, valid_array_t);
|
||||
static void fini_perfetto(int64_t _tid, valid_array_t);
|
||||
static void init_rocpd(int64_t _tid, valid_array_t);
|
||||
static void fini_rocpd(int64_t _tid, valid_array_t);
|
||||
static std::vector<std::string> get_hw_counter_labels(int64_t);
|
||||
|
||||
template <typename Tp>
|
||||
@@ -113,6 +115,7 @@ struct backtrace_metrics : comp::empty_base
|
||||
const auto& get_hw_counters() const { return m_hw_counter; }
|
||||
|
||||
void post_process_perfetto(int64_t _tid, uint64_t _ts) const;
|
||||
void post_process_rocpd(int64_t _tid, uint64_t _ts) const;
|
||||
|
||||
backtrace_metrics& operator-=(const backtrace_metrics&);
|
||||
|
||||
|
||||
@@ -21,15 +21,15 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#include "library/components/comm_data.hpp"
|
||||
#include "core/agent_manager.hpp"
|
||||
#include "core/components/fwd.hpp"
|
||||
#include "core/config.hpp"
|
||||
#include "core/node_info.hpp"
|
||||
#include "core/perfetto.hpp"
|
||||
#include "core/rocpd/data_processor.hpp"
|
||||
#include "library/tracing.hpp"
|
||||
|
||||
#include <timemory/backends/mpi.hpp>
|
||||
#include <timemory/manager.hpp>
|
||||
#include <timemory/units.hpp>
|
||||
#include <timemory/utility/locking.hpp>
|
||||
|
||||
namespace rocprofsys
|
||||
{
|
||||
@@ -74,6 +74,138 @@ write_perfetto_counter_track(uint64_t _val)
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace
|
||||
{
|
||||
rocpd::data_processor&
|
||||
get_data_processor()
|
||||
{
|
||||
return rocpd::data_processor::get_instance();
|
||||
}
|
||||
|
||||
void
|
||||
rocpd_initialize_comm_data_categories()
|
||||
{
|
||||
static bool _is_initialized = false;
|
||||
if(_is_initialized) return;
|
||||
|
||||
get_data_processor().insert_category(category_enum_id<category::comm_data>::value,
|
||||
trait::name<category::comm_data>::value);
|
||||
#if defined(ROCPROFSYS_USE_MPI)
|
||||
get_data_processor().insert_category(category_enum_id<category::mpi>::value,
|
||||
trait::name<category::mpi>::value);
|
||||
#endif
|
||||
#if defined(ROCPROFSYS_USE_RCCL)
|
||||
get_data_processor().insert_category(category_enum_id<category::rocm_rccl>::value,
|
||||
trait::name<category::rocm_rccl>::value);
|
||||
#endif
|
||||
_is_initialized = true;
|
||||
}
|
||||
|
||||
template <typename Track>
|
||||
void
|
||||
rocpd_initialize_track()
|
||||
{
|
||||
auto& n_info = node_info::get_instance();
|
||||
auto thread_id = std::nullopt;
|
||||
auto _init_track = [&](const char* label) {
|
||||
ROCPROFSYS_VERBOSE(3, "INSERT_TRACK label: %s, node ID: %d, Process ID: %d",
|
||||
label, n_info.id, getpid());
|
||||
get_data_processor().insert_track(label, n_info.id, getpid(), thread_id);
|
||||
};
|
||||
|
||||
static std::once_flag _once{};
|
||||
std::call_once(_once, _init_track, Track::label);
|
||||
}
|
||||
|
||||
void
|
||||
rocpd_initialize_comm_data_pmc()
|
||||
{
|
||||
[[maybe_unused]] auto& data_processor = get_data_processor();
|
||||
// find the proper values for a following definitions
|
||||
[[maybe_unused]] size_t EVENT_CODE = 0;
|
||||
[[maybe_unused]] size_t INSTANCE_ID = 0;
|
||||
[[maybe_unused]] constexpr const char* LONG_DESCRIPTION = "";
|
||||
[[maybe_unused]] constexpr const char* COMPONENT = "";
|
||||
[[maybe_unused]] constexpr const char* BLOCK = "";
|
||||
[[maybe_unused]] constexpr const char* EXPRESSION = "";
|
||||
[[maybe_unused]] constexpr const char* MSG = "bytes";
|
||||
[[maybe_unused]] constexpr const auto* TARGET_ARCH = "CPU";
|
||||
auto ni = node_info::get_instance();
|
||||
constexpr const auto DEVICE_ID = 0; // Assuming CPU device ID is 0
|
||||
|
||||
auto& _agent_manager = agent_manager::get_instance();
|
||||
[[maybe_unused]] auto base_id =
|
||||
_agent_manager.get_agent_by_id(DEVICE_ID, agent_type::CPU).base_id;
|
||||
|
||||
#if defined(ROCPROFSYS_USE_MPI)
|
||||
data_processor.insert_pmc_description(
|
||||
ni.id, getpid(), base_id, TARGET_ARCH, EVENT_CODE, INSTANCE_ID,
|
||||
comm_data::mpi_send::label, "Tracks MPI Send communication data sizes",
|
||||
trait::name<category::mpi>::description, LONG_DESCRIPTION, COMPONENT, MSG, "ABS",
|
||||
BLOCK, EXPRESSION, 0, 0);
|
||||
|
||||
data_processor.insert_pmc_description(
|
||||
ni.id, getpid(), base_id, TARGET_ARCH, EVENT_CODE, INSTANCE_ID,
|
||||
comm_data::mpi_recv::label, "Tracks MPI Receive communication data sizes",
|
||||
trait::name<category::mpi>::description, LONG_DESCRIPTION, COMPONENT, MSG, "ABS",
|
||||
BLOCK, EXPRESSION, 0, 0);
|
||||
#endif
|
||||
#if defined(ROCPROFSYS_USE_RCCL)
|
||||
data_processor.insert_pmc_description(
|
||||
ni.id, getpid(), base_id, TARGET_ARCH, EVENT_CODE, INSTANCE_ID, rccl_send::label,
|
||||
"Tracks RCCL Send communication data sizes",
|
||||
trait::name<category::rocm_rccl>::description, LONG_DESCRIPTION, COMPONENT, MSG,
|
||||
"ABS", BLOCK, EXPRESSION, 0, 0);
|
||||
|
||||
data_processor.insert_pmc_description(
|
||||
ni.id, getpid(), base_id, TARGET_ARCH, EVENT_CODE, INSTANCE_ID, rccl_recv::label,
|
||||
"Tracks RCCL Receive communication data sizes",
|
||||
trait::name<category::rocm_rccl>::description, LONG_DESCRIPTION, COMPONENT, MSG,
|
||||
"ABS", BLOCK, EXPRESSION, 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Track>
|
||||
void
|
||||
rocpd_process_cpu_usage_events(const uint32_t device_id, int bytes)
|
||||
{
|
||||
auto& data_processor = get_data_processor();
|
||||
auto event_id = data_processor.insert_event(
|
||||
category_enum_id<category::comm_data>::value, 0, 0, 0);
|
||||
|
||||
auto& agents = agent_manager::get_instance();
|
||||
auto agent = agents.get_agent_by_id(device_id, agent_type::CPU);
|
||||
|
||||
auto insert_event_and_sample = [&](const char* name, uint64_t timestamp,
|
||||
double value) {
|
||||
data_processor.insert_pmc_event(event_id, agent.device_id, name, value);
|
||||
data_processor.insert_sample(name, timestamp, event_id);
|
||||
};
|
||||
|
||||
static std::mutex _mutex{};
|
||||
static uint64_t value = 0;
|
||||
uint64_t _now = 0;
|
||||
{
|
||||
std::unique_lock<std::mutex> _lk{ _mutex };
|
||||
_now = rocprofsys::tracing::now<uint64_t>();
|
||||
bytes = (value += bytes);
|
||||
}
|
||||
|
||||
insert_event_and_sample(Track::label, _now, bytes);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void
|
||||
comm_data::start()
|
||||
{
|
||||
if(get_use_rocpd())
|
||||
{
|
||||
rocpd_initialize_comm_data_categories();
|
||||
rocpd_initialize_comm_data_pmc();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
comm_data::preinit()
|
||||
{
|
||||
@@ -116,13 +248,22 @@ comm_data::audit(const gotcha_data& _data, audit::incoming, const void*, int cou
|
||||
|
||||
write_perfetto_counter_track<mpi_send>(count * _size);
|
||||
|
||||
if(!rocprofsys::get_use_timemory()) return;
|
||||
auto _name = std::string_view{ _data.tool_id };
|
||||
tracker_t _a{ _name };
|
||||
add(_a, count * _size);
|
||||
tracker_t _b{ JOIN('/', _name, JOIN('=', "dst", dst)) };
|
||||
add(_b, count * _size);
|
||||
add(JOIN('/', _name, JOIN('=', "dst", dst), JOIN('=', "tag", tag)), count * _size);
|
||||
if(get_use_rocpd())
|
||||
{
|
||||
rocpd_initialize_track<mpi_send>();
|
||||
rocpd_process_cpu_usage_events<mpi_send>(0, count * _size);
|
||||
}
|
||||
|
||||
if(rocprofsys::get_use_timemory())
|
||||
{
|
||||
auto _name = std::string_view{ _data.tool_id };
|
||||
tracker_t _a{ _name };
|
||||
add(_a, count * _size);
|
||||
tracker_t _b{ JOIN('/', _name, JOIN('=', "dst", dst)) };
|
||||
add(_b, count * _size);
|
||||
add(JOIN('/', _name, JOIN('=', "dst", dst), JOIN('=', "tag", tag)),
|
||||
count * _size);
|
||||
}
|
||||
}
|
||||
|
||||
// MPI_Recv
|
||||
@@ -133,15 +274,24 @@ comm_data::audit(const gotcha_data& _data, audit::incoming, void*, int count,
|
||||
int _size = mpi_type_size(datatype);
|
||||
if(_size == 0) return;
|
||||
|
||||
write_perfetto_counter_track<mpi_recv>(count * _size);
|
||||
if(get_use_perfetto()) write_perfetto_counter_track<mpi_recv>(count * _size);
|
||||
|
||||
if(!rocprofsys::get_use_timemory()) return;
|
||||
auto _name = std::string_view{ _data.tool_id };
|
||||
tracker_t _a{ _name };
|
||||
add(_a, count * _size);
|
||||
tracker_t _b{ JOIN('/', _name, JOIN('=', "dst", dst)) };
|
||||
add(_b, count * _size);
|
||||
add(JOIN('/', _name, JOIN('=', "dst", dst), JOIN('=', "tag", tag)), count * _size);
|
||||
if(get_use_rocpd())
|
||||
{
|
||||
rocpd_initialize_track<mpi_recv>();
|
||||
rocpd_process_cpu_usage_events<mpi_recv>(0, count * _size);
|
||||
}
|
||||
|
||||
if(rocprofsys::get_use_timemory())
|
||||
{
|
||||
auto _name = std::string_view{ _data.tool_id };
|
||||
tracker_t _a{ _name };
|
||||
add(_a, count * _size);
|
||||
tracker_t _b{ JOIN('/', _name, JOIN('=', "dst", dst)) };
|
||||
add(_b, count * _size);
|
||||
add(JOIN('/', _name, JOIN('=', "dst", dst), JOIN('=', "tag", tag)),
|
||||
count * _size);
|
||||
}
|
||||
}
|
||||
|
||||
// MPI_Isend
|
||||
@@ -152,15 +302,24 @@ comm_data::audit(const gotcha_data& _data, audit::incoming, const void*, int cou
|
||||
int _size = mpi_type_size(datatype);
|
||||
if(_size == 0) return;
|
||||
|
||||
write_perfetto_counter_track<mpi_send>(count * _size);
|
||||
if(get_use_perfetto()) write_perfetto_counter_track<mpi_send>(count * _size);
|
||||
|
||||
if(!rocprofsys::get_use_timemory()) return;
|
||||
auto _name = std::string_view{ _data.tool_id };
|
||||
tracker_t _a{ _name };
|
||||
add(_a, count * _size);
|
||||
tracker_t _b{ JOIN('/', _name, JOIN('=', "dst", dst)) };
|
||||
add(_b, count * _size);
|
||||
add(JOIN('/', _name, JOIN('=', "dst", dst), JOIN('=', "tag", tag)), count * _size);
|
||||
if(get_use_rocpd())
|
||||
{
|
||||
rocpd_initialize_track<mpi_send>();
|
||||
rocpd_process_cpu_usage_events<mpi_send>(0, count * _size);
|
||||
}
|
||||
|
||||
if(rocprofsys::get_use_timemory())
|
||||
{
|
||||
auto _name = std::string_view{ _data.tool_id };
|
||||
tracker_t _a{ _name };
|
||||
add(_a, count * _size);
|
||||
tracker_t _b{ JOIN('/', _name, JOIN('=', "dst", dst)) };
|
||||
add(_b, count * _size);
|
||||
add(JOIN('/', _name, JOIN('=', "dst", dst), JOIN('=', "tag", tag)),
|
||||
count * _size);
|
||||
}
|
||||
}
|
||||
|
||||
// MPI_Irecv
|
||||
@@ -171,15 +330,24 @@ comm_data::audit(const gotcha_data& _data, audit::incoming, void*, int count,
|
||||
int _size = mpi_type_size(datatype);
|
||||
if(_size == 0) return;
|
||||
|
||||
write_perfetto_counter_track<mpi_recv>(count * _size);
|
||||
if(get_use_perfetto()) write_perfetto_counter_track<mpi_recv>(count * _size);
|
||||
|
||||
if(!rocprofsys::get_use_timemory()) return;
|
||||
auto _name = std::string_view{ _data.tool_id };
|
||||
tracker_t _a{ _name };
|
||||
add(_a, count * _size);
|
||||
tracker_t _b{ JOIN('/', _name, JOIN('=', "dst", dst)) };
|
||||
add(_b, count * _size);
|
||||
add(JOIN('/', _name, JOIN('=', "dst", dst), JOIN('=', "tag", tag)), count * _size);
|
||||
if(get_use_rocpd())
|
||||
{
|
||||
rocpd_initialize_track<mpi_recv>();
|
||||
rocpd_process_cpu_usage_events<mpi_recv>(0, count * _size);
|
||||
}
|
||||
|
||||
if(rocprofsys::get_use_timemory())
|
||||
{
|
||||
auto _name = std::string_view{ _data.tool_id };
|
||||
tracker_t _a{ _name };
|
||||
add(_a, count * _size);
|
||||
tracker_t _b{ JOIN('/', _name, JOIN('=', "dst", dst)) };
|
||||
add(_b, count * _size);
|
||||
add(JOIN('/', _name, JOIN('=', "dst", dst), JOIN('=', "tag", tag)),
|
||||
count * _size);
|
||||
}
|
||||
}
|
||||
|
||||
// MPI_Bcast
|
||||
@@ -190,13 +358,21 @@ comm_data::audit(const gotcha_data& _data, audit::incoming, void*, int count,
|
||||
int _size = mpi_type_size(datatype);
|
||||
if(_size == 0) return;
|
||||
|
||||
write_perfetto_counter_track<mpi_send>(count * _size);
|
||||
if(get_use_perfetto()) write_perfetto_counter_track<mpi_send>(count * _size);
|
||||
|
||||
if(!rocprofsys::get_use_timemory()) return;
|
||||
auto _name = std::string_view{ _data.tool_id };
|
||||
tracker_t _t{ _name };
|
||||
add(_t, count * _size);
|
||||
add(JOIN('/', _name, JOIN('=', "root", root)), count * _size);
|
||||
if(get_use_rocpd())
|
||||
{
|
||||
rocpd_initialize_track<mpi_send>();
|
||||
rocpd_process_cpu_usage_events<mpi_send>(0, count * _size);
|
||||
}
|
||||
|
||||
if(rocprofsys::get_use_timemory())
|
||||
{
|
||||
auto _name = std::string_view{ _data.tool_id };
|
||||
tracker_t _t{ _name };
|
||||
add(_t, count * _size);
|
||||
add(JOIN('/', _name, JOIN('=', "root", root)), count * _size);
|
||||
}
|
||||
}
|
||||
|
||||
// MPI_Allreduce
|
||||
@@ -207,11 +383,21 @@ comm_data::audit(const gotcha_data& _data, audit::incoming, const void*, void*,
|
||||
int _size = mpi_type_size(datatype);
|
||||
if(_size == 0) return;
|
||||
|
||||
write_perfetto_counter_track<mpi_recv>(count * _size);
|
||||
write_perfetto_counter_track<mpi_send>(count * _size);
|
||||
if(get_use_perfetto())
|
||||
{
|
||||
write_perfetto_counter_track<mpi_recv>(count * _size);
|
||||
write_perfetto_counter_track<mpi_send>(count * _size);
|
||||
}
|
||||
|
||||
if(!rocprofsys::get_use_timemory()) return;
|
||||
add(_data, count * _size);
|
||||
if(get_use_rocpd())
|
||||
{
|
||||
rocpd_initialize_track<mpi_send>();
|
||||
rocpd_initialize_track<mpi_recv>();
|
||||
rocpd_process_cpu_usage_events<mpi_recv>(0, count * _size);
|
||||
rocpd_process_cpu_usage_events<mpi_send>(0, count * _size);
|
||||
}
|
||||
|
||||
if(rocprofsys::get_use_timemory()) add(_data, count * _size);
|
||||
}
|
||||
|
||||
// MPI_Sendrecv
|
||||
@@ -224,30 +410,43 @@ comm_data::audit(const gotcha_data& _data, audit::incoming, const void*, int sen
|
||||
int _recv_size = mpi_type_size(recvtype);
|
||||
if(_send_size == 0 || _recv_size == 0) return;
|
||||
|
||||
write_perfetto_counter_track<mpi_send>(sendcount * _send_size);
|
||||
write_perfetto_counter_track<mpi_recv>(recvcount * _recv_size);
|
||||
|
||||
if(!rocprofsys::get_use_timemory()) return;
|
||||
auto _name = std::string_view{ _data.tool_id };
|
||||
tracker_t _t{ _name };
|
||||
add(_t, sendcount * _send_size + recvcount * _recv_size);
|
||||
if(get_use_perfetto())
|
||||
{
|
||||
tracker_t _b{ JOIN('/', _name, "send") };
|
||||
add(_b, sendcount * _send_size);
|
||||
tracker_t _c{ JOIN('/', _name, JOIN('=', "send", dst)) };
|
||||
add(_b, sendcount * _send_size);
|
||||
add(JOIN('/', _name, "send", JOIN('=', "tag", sendtag)), sendcount * _send_size);
|
||||
add(JOIN('/', _name, JOIN('=', "send", dst), JOIN('=', "tag", sendtag)),
|
||||
sendcount * _send_size);
|
||||
write_perfetto_counter_track<mpi_send>(sendcount * _send_size);
|
||||
write_perfetto_counter_track<mpi_recv>(recvcount * _recv_size);
|
||||
}
|
||||
|
||||
if(get_use_rocpd())
|
||||
{
|
||||
tracker_t _b{ JOIN('/', _name, "recv") };
|
||||
add(_b, recvcount * _recv_size);
|
||||
tracker_t _c{ JOIN('/', _name, JOIN('=', "recv", src)) };
|
||||
add(_b, recvcount * _recv_size);
|
||||
add(JOIN('/', _name, "recv", JOIN('=', "tag", recvtag)), recvcount * _recv_size);
|
||||
add(JOIN('/', _name, JOIN('=', "recv", src), JOIN('=', "tag", recvtag)),
|
||||
recvcount * _recv_size);
|
||||
rocpd_process_cpu_usage_events<mpi_send>(0, sendcount * _send_size);
|
||||
rocpd_process_cpu_usage_events<mpi_recv>(0, recvcount * _send_size);
|
||||
}
|
||||
|
||||
if(rocprofsys::get_use_timemory())
|
||||
{
|
||||
auto _name = std::string_view{ _data.tool_id };
|
||||
tracker_t _t{ _name };
|
||||
add(_t, sendcount * _send_size + recvcount * _recv_size);
|
||||
{
|
||||
tracker_t _b{ JOIN('/', _name, "send") };
|
||||
add(_b, sendcount * _send_size);
|
||||
tracker_t _c{ JOIN('/', _name, JOIN('=', "send", dst)) };
|
||||
add(_b, sendcount * _send_size);
|
||||
add(JOIN('/', _name, "send", JOIN('=', "tag", sendtag)),
|
||||
sendcount * _send_size);
|
||||
add(JOIN('/', _name, JOIN('=', "send", dst), JOIN('=', "tag", sendtag)),
|
||||
sendcount * _send_size);
|
||||
}
|
||||
{
|
||||
tracker_t _b{ JOIN('/', _name, "recv") };
|
||||
add(_b, recvcount * _recv_size);
|
||||
tracker_t _c{ JOIN('/', _name, JOIN('=', "recv", src)) };
|
||||
add(_b, recvcount * _recv_size);
|
||||
add(JOIN('/', _name, "recv", JOIN('=', "tag", recvtag)),
|
||||
recvcount * _recv_size);
|
||||
add(JOIN('/', _name, JOIN('=', "recv", src), JOIN('=', "tag", recvtag)),
|
||||
recvcount * _recv_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,17 +461,28 @@ comm_data::audit(const gotcha_data& _data, audit::incoming, const void*, int sen
|
||||
int _recv_size = mpi_type_size(recvtype);
|
||||
if(_send_size == 0 || _recv_size == 0) return;
|
||||
|
||||
write_perfetto_counter_track<mpi_send>(sendcount * _send_size);
|
||||
write_perfetto_counter_track<mpi_recv>(recvcount * _recv_size);
|
||||
if(get_use_perfetto())
|
||||
{
|
||||
write_perfetto_counter_track<mpi_send>(sendcount * _send_size);
|
||||
write_perfetto_counter_track<mpi_recv>(recvcount * _recv_size);
|
||||
}
|
||||
|
||||
if(!rocprofsys::get_use_timemory()) return;
|
||||
auto _name = std::string_view{ _data.tool_id };
|
||||
tracker_t _t{ _name };
|
||||
add(_t, sendcount * _send_size + recvcount * _recv_size);
|
||||
tracker_t _r(JOIN('/', _name, JOIN('=', "root", root)));
|
||||
add(_r, sendcount * _send_size + recvcount * _recv_size);
|
||||
add(JOIN('/', _name, JOIN('=', "root", root), "send"), sendcount * _send_size);
|
||||
add(JOIN('/', _name, JOIN('=', "root", root), "recv"), recvcount * _recv_size);
|
||||
if(get_use_rocpd())
|
||||
{
|
||||
rocpd_process_cpu_usage_events<mpi_send>(0, sendcount * _send_size);
|
||||
rocpd_process_cpu_usage_events<mpi_recv>(0, recvcount * _send_size);
|
||||
}
|
||||
|
||||
if(rocprofsys::get_use_timemory())
|
||||
{
|
||||
auto _name = std::string_view{ _data.tool_id };
|
||||
tracker_t _t{ _name };
|
||||
add(_t, sendcount * _send_size + recvcount * _recv_size);
|
||||
tracker_t _r(JOIN('/', _name, JOIN('=', "root", root)));
|
||||
add(_r, sendcount * _send_size + recvcount * _recv_size);
|
||||
add(JOIN('/', _name, JOIN('=', "root", root), "send"), sendcount * _send_size);
|
||||
add(JOIN('/', _name, JOIN('=', "root", root), "recv"), recvcount * _recv_size);
|
||||
}
|
||||
}
|
||||
|
||||
// MPI_Alltoall
|
||||
@@ -285,15 +495,26 @@ comm_data::audit(const gotcha_data& _data, audit::incoming, const void*, int sen
|
||||
int _recv_size = mpi_type_size(recvtype);
|
||||
if(_send_size == 0 || _recv_size == 0) return;
|
||||
|
||||
write_perfetto_counter_track<mpi_send>(sendcount * _send_size);
|
||||
write_perfetto_counter_track<mpi_recv>(recvcount * _recv_size);
|
||||
if(get_use_perfetto())
|
||||
{
|
||||
write_perfetto_counter_track<mpi_send>(sendcount * _send_size);
|
||||
write_perfetto_counter_track<mpi_recv>(recvcount * _recv_size);
|
||||
}
|
||||
|
||||
if(!rocprofsys::get_use_timemory()) return;
|
||||
auto _name = std::string_view{ _data.tool_id };
|
||||
tracker_t _t{ _name };
|
||||
add(_t, sendcount * _send_size + recvcount * _recv_size);
|
||||
add(JOIN('/', _name, "send"), sendcount * _send_size);
|
||||
add(JOIN('/', _name, "recv"), recvcount * _recv_size);
|
||||
if(get_use_rocpd())
|
||||
{
|
||||
rocpd_process_cpu_usage_events<mpi_send>(0, sendcount * _send_size);
|
||||
rocpd_process_cpu_usage_events<mpi_recv>(0, recvcount * _recv_size);
|
||||
}
|
||||
|
||||
if(rocprofsys::get_use_timemory())
|
||||
{
|
||||
auto _name = std::string_view{ _data.tool_id };
|
||||
tracker_t _t{ _name };
|
||||
add(_t, sendcount * _send_size + recvcount * _recv_size);
|
||||
add(JOIN('/', _name, "send"), sendcount * _send_size);
|
||||
add(JOIN('/', _name, "recv"), recvcount * _recv_size);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -309,13 +530,17 @@ comm_data::audit(const gotcha_data& _data, audit::incoming, const void*, const v
|
||||
int _size = rccl_type_size(datatype);
|
||||
if(_size <= 0) return;
|
||||
|
||||
write_perfetto_counter_track<rccl_recv>(count * _size);
|
||||
if(get_use_perfetto()) write_perfetto_counter_track<rccl_recv>(count * _size);
|
||||
|
||||
if(!rocprofsys::get_use_timemory()) return;
|
||||
auto _name = std::string_view{ _data.tool_id };
|
||||
tracker_t _t{ _name };
|
||||
add(_t, count * _size);
|
||||
add(JOIN('/', _name, JOIN('=', "root", root)), count * _size);
|
||||
if(get_use_rocpd()) rocpd_process_cpu_usage_events<rccl_recv>(0, count * _size);
|
||||
|
||||
if(rocprofsys::get_use_timemory())
|
||||
{
|
||||
auto _name = std::string_view{ _data.tool_id };
|
||||
tracker_t _t{ _name };
|
||||
add(_t, count * _size);
|
||||
add(JOIN('/', _name, JOIN('=', "root", root)), count * _size);
|
||||
}
|
||||
}
|
||||
|
||||
// ncclSend
|
||||
@@ -334,27 +559,32 @@ comm_data::audit(const gotcha_data& _data, audit::incoming, const void*, size_t
|
||||
|
||||
if(_send_types.count(_data.tool_id) > 0)
|
||||
{
|
||||
write_perfetto_counter_track<rccl_send>(count * _size);
|
||||
if(get_use_perfetto()) write_perfetto_counter_track<rccl_send>(count * _size);
|
||||
if(get_use_rocpd()) rocpd_process_cpu_usage_events<rccl_send>(0, count * _size);
|
||||
}
|
||||
else if(_recv_types.count(_data.tool_id) > 0)
|
||||
{
|
||||
write_perfetto_counter_track<rccl_recv>(count * _size);
|
||||
if(get_use_perfetto()) write_perfetto_counter_track<rccl_recv>(count * _size);
|
||||
if(get_use_rocpd()) rocpd_process_cpu_usage_events<rccl_recv>(0, count * _size);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROCPROFSYS_CI_THROW(true, "RCCL function not handled: %s", _data.tool_id.c_str());
|
||||
}
|
||||
|
||||
write_perfetto_counter_track<rccl_recv>(count * _size);
|
||||
if(get_use_perfetto()) write_perfetto_counter_track<rccl_recv>(count * _size);
|
||||
if(get_use_rocpd()) rocpd_process_cpu_usage_events<rccl_recv>(0, count * _size);
|
||||
|
||||
if(!rocprofsys::get_use_timemory()) return;
|
||||
auto _name = std::string_view{ _data.tool_id };
|
||||
std::string _label = "root";
|
||||
if(_name.find("Send") != std::string::npos) _label = "peer";
|
||||
if(rocprofsys::get_use_timemory())
|
||||
{
|
||||
auto _name = std::string_view{ _data.tool_id };
|
||||
std::string _label = "root";
|
||||
if(_name.find("Send") != std::string::npos) _label = "peer";
|
||||
|
||||
tracker_t _t{ _name };
|
||||
add(_t, count * _size);
|
||||
add(JOIN('/', _name, JOIN('=', _label, peer)), count * _size);
|
||||
tracker_t _t{ _name };
|
||||
add(_t, count * _size);
|
||||
add(JOIN('/', _name, JOIN('=', _label, peer)), count * _size);
|
||||
}
|
||||
}
|
||||
|
||||
// ncclBroadcast
|
||||
@@ -365,13 +595,16 @@ comm_data::audit(const gotcha_data& _data, audit::incoming, const void*, const v
|
||||
int _size = rccl_type_size(datatype);
|
||||
if(_size <= 0) return;
|
||||
|
||||
write_perfetto_counter_track<rccl_send>(count * _size);
|
||||
if(get_use_perfetto()) write_perfetto_counter_track<rccl_send>(count * _size);
|
||||
if(get_use_rocpd()) rocpd_process_cpu_usage_events<rccl_send>(0, count * _size);
|
||||
|
||||
if(!rocprofsys::get_use_timemory()) return;
|
||||
auto _name = std::string_view{ _data.tool_id };
|
||||
tracker_t _t{ _name };
|
||||
add(_t, count * _size);
|
||||
add(JOIN('/', _data.tool_id, JOIN('=', "root", root)), count * _size);
|
||||
if(rocprofsys::get_use_timemory())
|
||||
{
|
||||
auto _name = std::string_view{ _data.tool_id };
|
||||
tracker_t _t{ _name };
|
||||
add(_t, count * _size);
|
||||
add(JOIN('/', _data.tool_id, JOIN('=', "root", root)), count * _size);
|
||||
}
|
||||
}
|
||||
|
||||
// ncclAllReduce
|
||||
@@ -389,19 +622,20 @@ comm_data::audit(const gotcha_data& _data, audit::incoming, const void*, const v
|
||||
|
||||
if(_send_types.count(_data.tool_id) > 0)
|
||||
{
|
||||
write_perfetto_counter_track<rccl_send>(count * _size);
|
||||
if(get_use_perfetto()) write_perfetto_counter_track<rccl_send>(count * _size);
|
||||
if(get_use_rocpd()) rocpd_process_cpu_usage_events<rccl_send>(0, count * _size);
|
||||
}
|
||||
else if(_recv_types.count(_data.tool_id) > 0)
|
||||
{
|
||||
write_perfetto_counter_track<rccl_recv>(count * _size);
|
||||
if(get_use_perfetto()) write_perfetto_counter_track<rccl_recv>(count * _size);
|
||||
if(get_use_rocpd()) rocpd_process_cpu_usage_events<rccl_recv>(0, count * _size);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROCPROFSYS_CI_THROW(true, "RCCL function not handled: %s", _data.tool_id.c_str());
|
||||
}
|
||||
|
||||
if(!rocprofsys::get_use_timemory()) return;
|
||||
add(_data, count * _size);
|
||||
if(rocprofsys::get_use_timemory()) add(_data, count * _size);
|
||||
}
|
||||
|
||||
// ncclAllGather
|
||||
@@ -413,10 +647,9 @@ comm_data::audit(const gotcha_data& _data, audit::incoming, const void*, const v
|
||||
int _size = rccl_type_size(datatype);
|
||||
if(_size <= 0) return;
|
||||
|
||||
write_perfetto_counter_track<rccl_recv>(count * _size);
|
||||
|
||||
if(!rocprofsys::get_use_timemory()) return;
|
||||
add(_data, count * _size);
|
||||
if(get_use_perfetto()) write_perfetto_counter_track<rccl_recv>(count * _size);
|
||||
if(get_use_rocpd()) rocpd_process_cpu_usage_events<rccl_recv>(0, count * _size);
|
||||
if(rocprofsys::get_use_timemory()) add(_data, count * _size);
|
||||
}
|
||||
#endif
|
||||
} // namespace component
|
||||
|
||||
@@ -82,7 +82,7 @@ struct comm_data : base<comm_data, void>
|
||||
static void preinit();
|
||||
static void configure();
|
||||
static void global_finalize();
|
||||
static void start() {}
|
||||
static void start();
|
||||
static void stop() {}
|
||||
|
||||
#if defined(ROCPROFSYS_USE_MPI)
|
||||
|
||||
@@ -21,15 +21,15 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#include "library/cpu_freq.hpp"
|
||||
#include "core/agent.hpp"
|
||||
#include "core/agent_manager.hpp"
|
||||
#include "core/common.hpp"
|
||||
#include "core/components/fwd.hpp"
|
||||
#include "core/config.hpp"
|
||||
#include "core/debug.hpp"
|
||||
#include "core/defines.hpp"
|
||||
#include "core/node_info.hpp"
|
||||
#include "core/perfetto.hpp"
|
||||
#include "core/timemory.hpp"
|
||||
#include "core/rocpd/data_processor.hpp"
|
||||
#include "library/components/cpu_freq.hpp"
|
||||
#include "library/thread_data.hpp"
|
||||
#include "library/thread_info.hpp"
|
||||
|
||||
#include <timemory/components/rusage/backends.hpp>
|
||||
@@ -44,7 +44,6 @@
|
||||
#include <sys/resource.h>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace rocprofsys
|
||||
{
|
||||
@@ -65,6 +64,181 @@ init_perfetto_counter_tracks(type_list<Types...>)
|
||||
{
|
||||
(perfetto_counter_track<Types>::init(), ...);
|
||||
}
|
||||
|
||||
template <typename Category>
|
||||
inline std::string
|
||||
get_cpu_freq_track_name(uint64_t cpu_id)
|
||||
{
|
||||
return std::string(trait::name<Category>::value) + " [" + std::to_string(cpu_id) +
|
||||
"]";
|
||||
}
|
||||
|
||||
template <typename Func>
|
||||
void
|
||||
do_for_enabled_cpus(Func&& func)
|
||||
{
|
||||
const auto& enabled_cpus = component::cpu_freq::get_enabled_cpus();
|
||||
for(const auto& cpu : enabled_cpus)
|
||||
{
|
||||
func(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
rocpd::data_processor&
|
||||
get_data_processor()
|
||||
{
|
||||
return rocpd::data_processor::get_instance();
|
||||
}
|
||||
|
||||
void
|
||||
rocpd_initialize_cpu_freq_category()
|
||||
{
|
||||
get_data_processor().insert_category(ROCPROFSYS_CATEGORY_CPU_FREQ,
|
||||
trait::name<category::cpu_freq>::value);
|
||||
}
|
||||
|
||||
void
|
||||
rocpd_initialize_cpu_freq_tracks()
|
||||
{
|
||||
auto& data_processor = get_data_processor();
|
||||
auto& n_info = node_info::get_instance();
|
||||
const auto thread_idx = std::nullopt; // Internal thread ID for cpu-freq
|
||||
|
||||
do_for_enabled_cpus([&](size_t cpu_id) {
|
||||
data_processor.insert_track(
|
||||
get_cpu_freq_track_name<category::cpu_freq>(cpu_id).c_str(), n_info.id,
|
||||
getpid(), thread_idx);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
rocpd_initialize_cpu_usage_tracks()
|
||||
{
|
||||
auto& data_processor = get_data_processor();
|
||||
auto& n_info = node_info::get_instance();
|
||||
const auto thread_idx = std::nullopt; // Internal thread ID for cpu-freq
|
||||
|
||||
data_processor.insert_track(trait::name<category::process_page>::value, n_info.id,
|
||||
getpid(), thread_idx);
|
||||
data_processor.insert_track(trait::name<category::process_virt>::value, n_info.id,
|
||||
getpid(), thread_idx);
|
||||
data_processor.insert_track(trait::name<category::process_peak>::value, n_info.id,
|
||||
getpid(), thread_idx);
|
||||
data_processor.insert_track(trait::name<category::process_context_switch>::value,
|
||||
n_info.id, getpid(), thread_idx);
|
||||
data_processor.insert_track(trait::name<category::process_page_fault>::value,
|
||||
n_info.id, getpid(), thread_idx);
|
||||
data_processor.insert_track(trait::name<category::process_user_mode_time>::value,
|
||||
n_info.id, getpid(), thread_idx);
|
||||
data_processor.insert_track(trait::name<category::process_kernel_mode_time>::value,
|
||||
n_info.id, getpid(), thread_idx);
|
||||
}
|
||||
|
||||
void
|
||||
rocpd_initialize_cpu_freq_pmc(size_t dev_id)
|
||||
{
|
||||
auto& data_processor = get_data_processor();
|
||||
// find the proper values for a following definitions
|
||||
size_t EVENT_CODE = 0;
|
||||
size_t INSTANCE_ID = 0;
|
||||
const char* LONG_DESCRIPTION = "";
|
||||
const char* COMPONENT = "";
|
||||
const char* BLOCK = "";
|
||||
const char* EXPRESSION = "";
|
||||
const char* MEMORY = "MB";
|
||||
const char* TIME = "sec";
|
||||
auto ni = node_info::get_instance();
|
||||
const auto* TARGET_ARCH = "CPU";
|
||||
|
||||
auto& _agent_manager = agent_manager::get_instance();
|
||||
auto base_id = _agent_manager.get_agent_by_id(dev_id, agent_type::CPU).base_id;
|
||||
|
||||
do_for_enabled_cpus([&](size_t cpu_id) {
|
||||
data_processor.insert_pmc_description(
|
||||
ni.id, getpid(), base_id, TARGET_ARCH, EVENT_CODE, INSTANCE_ID,
|
||||
get_cpu_freq_track_name<category::cpu_freq>(cpu_id).c_str(), "Frequency",
|
||||
trait::name<category::cpu_freq>::description, LONG_DESCRIPTION, COMPONENT,
|
||||
component::cpu_freq::display_unit().c_str(), "ABS", BLOCK, EXPRESSION, 0, 0);
|
||||
});
|
||||
|
||||
data_processor.insert_pmc_description(
|
||||
ni.id, getpid(), base_id, TARGET_ARCH, EVENT_CODE, INSTANCE_ID,
|
||||
trait::name<category::process_page>::value, "Memory Usage",
|
||||
trait::name<category::process_page>::description, LONG_DESCRIPTION, COMPONENT,
|
||||
MEMORY, "ABS", BLOCK, EXPRESSION, 0, 0);
|
||||
|
||||
data_processor.insert_pmc_description(
|
||||
ni.id, getpid(), base_id, TARGET_ARCH, EVENT_CODE, INSTANCE_ID,
|
||||
trait::name<category::process_virt>::value, "Virtual Memory Usage",
|
||||
trait::name<category::process_virt>::description, LONG_DESCRIPTION, COMPONENT,
|
||||
MEMORY, "ABS", BLOCK, EXPRESSION, 0, 0);
|
||||
|
||||
data_processor.insert_pmc_description(
|
||||
ni.id, getpid(), base_id, TARGET_ARCH, EVENT_CODE, INSTANCE_ID,
|
||||
trait::name<category::process_peak>::value, "Peak Memory",
|
||||
trait::name<category::process_peak>::description, LONG_DESCRIPTION, COMPONENT,
|
||||
MEMORY, "ABS", BLOCK, EXPRESSION, 0, 0);
|
||||
|
||||
data_processor.insert_pmc_description(
|
||||
ni.id, getpid(), base_id, TARGET_ARCH, EVENT_CODE, INSTANCE_ID,
|
||||
trait::name<category::process_context_switch>::value, "Context Switches",
|
||||
trait::name<category::process_context_switch>::description, LONG_DESCRIPTION,
|
||||
COMPONENT, "", "ABS", BLOCK, EXPRESSION, 0, 0);
|
||||
|
||||
data_processor.insert_pmc_description(
|
||||
ni.id, getpid(), base_id, TARGET_ARCH, EVENT_CODE, INSTANCE_ID,
|
||||
trait::name<category::process_page_fault>::value, "Page Faults",
|
||||
trait::name<category::process_page_fault>::description, LONG_DESCRIPTION,
|
||||
COMPONENT, "", "ABS", BLOCK, EXPRESSION, 0, 0);
|
||||
|
||||
data_processor.insert_pmc_description(
|
||||
ni.id, getpid(), base_id, TARGET_ARCH, EVENT_CODE, INSTANCE_ID,
|
||||
trait::name<category::process_user_mode_time>::value, "User Time",
|
||||
trait::name<category::process_user_mode_time>::description, LONG_DESCRIPTION,
|
||||
COMPONENT, TIME, "ABS", BLOCK, EXPRESSION, 0, 0);
|
||||
|
||||
data_processor.insert_pmc_description(
|
||||
ni.id, getpid(), base_id, TARGET_ARCH, EVENT_CODE, INSTANCE_ID,
|
||||
trait::name<category::process_kernel_mode_time>::value, "Kernel Time",
|
||||
trait::name<category::process_kernel_mode_time>::description, LONG_DESCRIPTION,
|
||||
COMPONENT, TIME, "ABS", BLOCK, EXPRESSION, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
rocpd_process_cpu_usage_events(const uint32_t device_id, uint64_t timestamp,
|
||||
const component::cpu_freq& freq, double mem_page,
|
||||
double virt_mem_page, double peak_mem,
|
||||
double context_switch, double page_fault, double user_time,
|
||||
double kernel_time)
|
||||
{
|
||||
auto& data_processor = get_data_processor();
|
||||
auto event_id = data_processor.insert_event(ROCPROFSYS_CATEGORY_CPU_FREQ, 0, 0, 0);
|
||||
|
||||
auto& agent_mngr = agent_manager::get_instance();
|
||||
auto base_id = agent_mngr.get_agent_by_id(device_id, agent_type::CPU).base_id;
|
||||
|
||||
auto insert_event_and_sample = [&](const char* name, double value) {
|
||||
data_processor.insert_pmc_event(event_id, base_id, name, value);
|
||||
data_processor.insert_sample(name, timestamp, event_id);
|
||||
};
|
||||
|
||||
do_for_enabled_cpus([&](size_t cpu_id) {
|
||||
insert_event_and_sample(
|
||||
get_cpu_freq_track_name<category::cpu_freq>(cpu_id).c_str(), freq.at(cpu_id));
|
||||
});
|
||||
|
||||
insert_event_and_sample(trait::name<category::process_page>::value, mem_page);
|
||||
insert_event_and_sample(trait::name<category::process_virt>::value, virt_mem_page);
|
||||
insert_event_and_sample(trait::name<category::process_peak>::value, peak_mem);
|
||||
insert_event_and_sample(trait::name<category::process_context_switch>::value,
|
||||
context_switch);
|
||||
insert_event_and_sample(trait::name<category::process_page_fault>::value, page_fault);
|
||||
insert_event_and_sample(trait::name<category::process_user_mode_time>::value,
|
||||
user_time);
|
||||
insert_event_and_sample(trait::name<category::process_kernel_mode_time>::value,
|
||||
kernel_time);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace cpu_freq
|
||||
} // namespace rocprofsys
|
||||
@@ -76,11 +250,14 @@ namespace cpu_freq
|
||||
void
|
||||
setup()
|
||||
{
|
||||
init_perfetto_counter_tracks(
|
||||
type_list<category::cpu_freq, category::process_page, category::process_virt,
|
||||
category::process_peak, category::process_context_switch,
|
||||
category::process_page_fault, category::process_user_mode_time,
|
||||
category::process_kernel_mode_time>{});
|
||||
if(get_use_perfetto())
|
||||
{
|
||||
init_perfetto_counter_tracks(
|
||||
type_list<category::cpu_freq, category::process_page, category::process_virt,
|
||||
category::process_peak, category::process_context_switch,
|
||||
category::process_page_fault, category::process_user_mode_time,
|
||||
category::process_kernel_mode_time>{});
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -163,6 +340,28 @@ post_process()
|
||||
ROCPROFSYS_VERBOSE(1,
|
||||
"Post-processing %zu cpu frequency and memory usage entries...\n",
|
||||
data.size());
|
||||
|
||||
auto& enabled_cpus = component::cpu_freq::get_enabled_cpus();
|
||||
|
||||
if(get_use_rocpd())
|
||||
{
|
||||
rocpd_initialize_cpu_freq_category();
|
||||
rocpd_initialize_cpu_usage_tracks();
|
||||
rocpd_initialize_cpu_freq_tracks();
|
||||
|
||||
// `get_enabled_cpus()` returns the number of cores enabled for monitoring but the
|
||||
// actually device_id is 0, since there is a single device available. And the
|
||||
// agents seems to be assigned per device basis not per core.
|
||||
// TODO: `get_enabled_cpus()` should be fixed in the future to align with GPU
|
||||
// implementation.
|
||||
auto cpu_agents =
|
||||
agent_manager::get_instance().get_agents_by_type(agent_type::CPU);
|
||||
for(auto& agent : cpu_agents)
|
||||
{
|
||||
rocpd_initialize_cpu_freq_pmc(agent->device_id);
|
||||
}
|
||||
}
|
||||
|
||||
auto _process_frequencies = [](size_t _idx, size_t _offset) {
|
||||
using freq_track = perfetto_counter_track<category::cpu_freq>;
|
||||
|
||||
@@ -191,14 +390,17 @@ post_process()
|
||||
};
|
||||
|
||||
auto _process_cpu_rusage = []() {
|
||||
config_perfetto_counter_tracks(
|
||||
type_list<category::process_page, category::process_virt,
|
||||
category::process_peak, category::process_context_switch,
|
||||
category::process_page_fault, category::process_user_mode_time,
|
||||
category::process_kernel_mode_time>{},
|
||||
{ "Memory Usage", "Virtual Memory Usage", "Peak Memory", "Context Switches",
|
||||
"Page Faults", "User Time", "Kernel Time" },
|
||||
{ "MB", "MB", "MB", "", "", "sec", "sec" });
|
||||
if(get_use_perfetto())
|
||||
{
|
||||
config_perfetto_counter_tracks(
|
||||
type_list<category::process_page, category::process_virt,
|
||||
category::process_peak, category::process_context_switch,
|
||||
category::process_page_fault, category::process_user_mode_time,
|
||||
category::process_kernel_mode_time>{},
|
||||
{ "Memory Usage", "Virtual Memory Usage", "Peak Memory",
|
||||
"Context Switches", "Page Faults", "User Time", "Kernel Time" },
|
||||
{ "MB", "MB", "MB", "", "", "sec", "sec" });
|
||||
}
|
||||
|
||||
const auto& _thread_info = thread_info::get(0, InternalTID);
|
||||
ROCPROFSYS_CI_THROW(!_thread_info, "Missing thread info for thread 0");
|
||||
@@ -209,47 +411,61 @@ post_process()
|
||||
uint64_t _ts = std::get<0>(itr);
|
||||
if(!_thread_info->is_valid_time(_ts)) continue;
|
||||
|
||||
double _page = std::get<1>(itr);
|
||||
double _virt = std::get<2>(itr);
|
||||
double _peak = std::get<3>(itr);
|
||||
double _page = std::get<1>(itr) / units::megabyte;
|
||||
double _virt = std::get<2>(itr) / units::megabyte;
|
||||
double _peak = std::get<3>(itr) / units::megabyte;
|
||||
uint64_t _cntx = std::get<4>(itr);
|
||||
uint64_t _flts = std::get<5>(itr);
|
||||
double _user = std::get<6>(itr);
|
||||
double _kern = std::get<7>(itr);
|
||||
write_perfetto_counter_track<category::process_page>(_ts,
|
||||
_page / units::megabyte);
|
||||
write_perfetto_counter_track<category::process_virt>(_ts,
|
||||
_virt / units::megabyte);
|
||||
write_perfetto_counter_track<category::process_peak>(_ts,
|
||||
_peak / units::megabyte);
|
||||
write_perfetto_counter_track<category::process_context_switch>(_ts, _cntx);
|
||||
write_perfetto_counter_track<category::process_page_fault>(_ts, _flts);
|
||||
write_perfetto_counter_track<category::process_user_mode_time>(
|
||||
_ts, _user / units::sec);
|
||||
write_perfetto_counter_track<category::process_kernel_mode_time>(
|
||||
_ts, _kern / units::sec);
|
||||
double _user = std::get<6>(itr) / units::sec;
|
||||
double _kern = std::get<7>(itr) / units::sec;
|
||||
if(get_use_perfetto())
|
||||
{
|
||||
write_perfetto_counter_track<category::process_page>(_ts, _page);
|
||||
write_perfetto_counter_track<category::process_virt>(_ts, _virt);
|
||||
write_perfetto_counter_track<category::process_peak>(_ts, _peak);
|
||||
write_perfetto_counter_track<category::process_context_switch>(_ts,
|
||||
_cntx);
|
||||
write_perfetto_counter_track<category::process_page_fault>(_ts, _flts);
|
||||
write_perfetto_counter_track<category::process_user_mode_time>(_ts,
|
||||
_user);
|
||||
write_perfetto_counter_track<category::process_kernel_mode_time>(_ts,
|
||||
_kern);
|
||||
}
|
||||
if(get_use_rocpd())
|
||||
{
|
||||
const auto& freq_data = std::get<8>(itr);
|
||||
rocpd_process_cpu_usage_events(0, _ts, freq_data, _page, _virt, _peak,
|
||||
_cntx, _flts, _user, _kern);
|
||||
}
|
||||
}
|
||||
|
||||
auto _end_ts = _thread_info->get_stop();
|
||||
write_perfetto_counter_track<category::process_page>(_end_ts, 0.0);
|
||||
write_perfetto_counter_track<category::process_virt>(_end_ts, 0.0);
|
||||
write_perfetto_counter_track<category::process_peak>(_end_ts, 0.0);
|
||||
write_perfetto_counter_track<category::process_context_switch>(_end_ts, 0);
|
||||
write_perfetto_counter_track<category::process_page_fault>(_end_ts, 0);
|
||||
write_perfetto_counter_track<category::process_user_mode_time>(_end_ts, 0.0);
|
||||
write_perfetto_counter_track<category::process_kernel_mode_time>(_end_ts, 0.0);
|
||||
if(get_use_perfetto())
|
||||
{
|
||||
auto _end_ts = _thread_info->get_stop();
|
||||
write_perfetto_counter_track<category::process_page>(_end_ts, 0.0);
|
||||
write_perfetto_counter_track<category::process_virt>(_end_ts, 0.0);
|
||||
write_perfetto_counter_track<category::process_peak>(_end_ts, 0.0);
|
||||
write_perfetto_counter_track<category::process_context_switch>(_end_ts, 0);
|
||||
write_perfetto_counter_track<category::process_page_fault>(_end_ts, 0);
|
||||
write_perfetto_counter_track<category::process_user_mode_time>(_end_ts, 0.0);
|
||||
write_perfetto_counter_track<category::process_kernel_mode_time>(_end_ts,
|
||||
0.0);
|
||||
}
|
||||
};
|
||||
|
||||
_process_cpu_rusage();
|
||||
|
||||
auto& enabled_cpu_freqs = component::cpu_freq::get_enabled_cpus();
|
||||
for(auto itr = enabled_cpu_freqs.begin(); itr != enabled_cpu_freqs.end(); ++itr)
|
||||
if(get_use_perfetto())
|
||||
{
|
||||
auto _idx = *itr;
|
||||
auto _offset = std::distance(enabled_cpu_freqs.begin(), itr);
|
||||
_process_frequencies(_idx, _offset);
|
||||
for(auto itr = enabled_cpus.begin(); itr != enabled_cpus.end(); ++itr)
|
||||
{
|
||||
auto _idx = *itr;
|
||||
auto _offset = std::distance(enabled_cpus.begin(), itr);
|
||||
_process_frequencies(_idx, _offset);
|
||||
}
|
||||
}
|
||||
enabled_cpu_freqs.clear();
|
||||
enabled_cpus.clear();
|
||||
}
|
||||
|
||||
} // namespace cpu_freq
|
||||
} // namespace rocprofsys
|
||||
|
||||
@@ -20,14 +20,19 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include <optional>
|
||||
#define TIMEMORY_KOKKOSP_POSTFIX ROCPROFSYS_PUBLIC_API
|
||||
|
||||
#include "api.hpp"
|
||||
#include "core/agent_manager.hpp"
|
||||
#include "core/components/fwd.hpp"
|
||||
#include "core/config.hpp"
|
||||
#include "core/debug.hpp"
|
||||
#include "core/defines.hpp"
|
||||
#include "core/node_info.hpp"
|
||||
#include "core/perfetto.hpp"
|
||||
#include "core/rocpd/data_processor.hpp"
|
||||
#include "core/rocpd/json.hpp"
|
||||
#include "library/components/category_region.hpp"
|
||||
#include "library/runtime.hpp"
|
||||
|
||||
@@ -150,6 +155,52 @@ violates_name_rules(Arg&& _arg, Args&&... _args)
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace
|
||||
{
|
||||
rocprofsys::rocpd::data_processor&
|
||||
get_data_processor()
|
||||
{
|
||||
return rocprofsys::rocpd::data_processor::get_instance();
|
||||
}
|
||||
|
||||
void
|
||||
rocpd_initialize_kokkos_category()
|
||||
{
|
||||
get_data_processor().insert_category(
|
||||
rocprofsys::category_enum_id<category::kokkos>::value,
|
||||
rocprofsys::trait::name<category::kokkos>::value);
|
||||
}
|
||||
|
||||
void
|
||||
rocpd_initialize_kokkos_track()
|
||||
{
|
||||
auto& data_processor = get_data_processor();
|
||||
auto& n_info = rocprofsys::node_info::get_instance();
|
||||
auto thread_id = std::nullopt;
|
||||
|
||||
data_processor.insert_track(rocprofsys::trait::name<category::kokkos>::value,
|
||||
n_info.id, getpid(), thread_id);
|
||||
}
|
||||
|
||||
void
|
||||
rocpd_process_kokkos_event(const char* name, const char* event_type, const char* target,
|
||||
uint64_t timestamp_ns)
|
||||
{
|
||||
auto& data_processor = get_data_processor();
|
||||
auto event_metadata = rocpd::json::create();
|
||||
|
||||
event_metadata->set("name", name);
|
||||
event_metadata->set("event_type", event_type);
|
||||
event_metadata->set("target", target);
|
||||
|
||||
auto event_id = data_processor.insert_event(
|
||||
rocprofsys::category_enum_id<category::kokkos>::value, 0, 0, 0, "{}", "{}",
|
||||
event_metadata->to_string().c_str());
|
||||
data_processor.insert_sample(rocprofsys::trait::name<category::kokkos>::value,
|
||||
timestamp_ns, event_id, "{}");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
extern "C"
|
||||
@@ -256,6 +307,12 @@ extern "C"
|
||||
rocprofsys_set_mpi_hidden(false, false);
|
||||
rocprofsys_init_hidden(_mode.c_str(), false, _arg0.c_str());
|
||||
rocprofsys_push_trace_hidden("kokkos_main");
|
||||
|
||||
if(rocprofsys::get_use_rocpd())
|
||||
{
|
||||
rocpd_initialize_kokkos_category();
|
||||
rocpd_initialize_kokkos_track();
|
||||
}
|
||||
}
|
||||
|
||||
setup_kernel_logger();
|
||||
@@ -545,6 +602,8 @@ extern "C"
|
||||
{
|
||||
if(violates_name_rules(label)) return;
|
||||
|
||||
auto timestamp = tim::get_clock_real_now<uint64_t, std::nano>();
|
||||
|
||||
ROCPROFSYS_SCOPED_THREAD_STATE(ThreadState::Internal);
|
||||
if(rocprofsys::config::get_use_perfetto())
|
||||
{
|
||||
@@ -559,12 +618,20 @@ extern "C"
|
||||
"", label, " [dual_view_sync][", (is_device) ? "device" : "host", "]")));
|
||||
kokkosp::profiler_t<kokkosp_region>{ _name }.mark();
|
||||
}
|
||||
|
||||
if(rocprofsys::config::get_use_rocpd())
|
||||
{
|
||||
rocpd_process_kokkos_event(JOIN(" ", _kp_prefix, label).c_str(),
|
||||
"[dual_view_sync]",
|
||||
(is_device) ? "device" : "host", timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
void kokkosp_dual_view_modify(const char* label, const void* const, bool is_device)
|
||||
{
|
||||
if(violates_name_rules(label)) return;
|
||||
|
||||
auto timestamp = tim::get_clock_real_now<uint64_t, std::nano>();
|
||||
ROCPROFSYS_SCOPED_THREAD_STATE(ThreadState::Internal);
|
||||
if(rocprofsys::config::get_use_perfetto())
|
||||
{
|
||||
@@ -580,6 +647,13 @@ extern "C"
|
||||
(is_device) ? "device" : "host", "]")));
|
||||
kokkosp::profiler_t<kokkosp_region>{ _name }.mark();
|
||||
}
|
||||
|
||||
if(rocprofsys::config::get_use_rocpd())
|
||||
{
|
||||
rocpd_process_kokkos_event(JOIN(" ", _kp_prefix, label).c_str(),
|
||||
"[dual_view_modify]",
|
||||
(is_device) ? "device" : "host", timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------//
|
||||
|
||||
@@ -21,26 +21,10 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#include "library/rocprofiler-sdk/counters.hpp"
|
||||
#include "common/synchronized.hpp"
|
||||
#include "core/debug.hpp"
|
||||
#include "core/timemory.hpp"
|
||||
#include "library/rocprofiler-sdk/fwd.hpp"
|
||||
|
||||
#include <timemory/utility/types.hpp>
|
||||
|
||||
#include <rocprofiler-sdk/agent.h>
|
||||
#include <rocprofiler-sdk/buffer_tracing.h>
|
||||
#include <rocprofiler-sdk/callback_tracing.h>
|
||||
#include <rocprofiler-sdk/cxx/hash.hpp>
|
||||
#include <rocprofiler-sdk/cxx/name_info.hpp>
|
||||
#include <rocprofiler-sdk/cxx/operators.hpp>
|
||||
#include <rocprofiler-sdk/dispatch_counting_service.h>
|
||||
#include <rocprofiler-sdk/fwd.h>
|
||||
#include <rocprofiler-sdk/registration.h>
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <timemory/utility/types.hpp>
|
||||
|
||||
namespace rocprofsys
|
||||
{
|
||||
|
||||
@@ -26,7 +26,10 @@
|
||||
#include "core/config.hpp"
|
||||
#include "core/debug.hpp"
|
||||
#include "core/locking.hpp"
|
||||
#include "core/node_info.hpp"
|
||||
#include "core/perf.hpp"
|
||||
#include "core/rocpd/data_processor.hpp"
|
||||
#include "core/rocpd/json.hpp"
|
||||
#include "core/state.hpp"
|
||||
#include "core/utility.hpp"
|
||||
#include "library/components/backtrace.hpp"
|
||||
@@ -153,6 +156,136 @@ namespace
|
||||
{
|
||||
using sampler_allocator_t = typename sampler_t::allocator_t;
|
||||
|
||||
template <typename Category>
|
||||
inline std::string
|
||||
get_category_track_name(uint64_t tid)
|
||||
{
|
||||
return std::string(trait::name<Category>::value) + "_" + std::to_string(tid);
|
||||
}
|
||||
|
||||
std::string
|
||||
generate_call_stack_json(const tim::unwind::processed_entry& stack_entry)
|
||||
{
|
||||
auto call_stack = ::rocpd::json::create();
|
||||
|
||||
call_stack->set("name", std::string(demangle(stack_entry.name)));
|
||||
call_stack->set("pc", as_hex(stack_entry.address));
|
||||
call_stack->set("file", std::string(stack_entry.location));
|
||||
|
||||
return call_stack->to_string();
|
||||
}
|
||||
|
||||
std::string
|
||||
generate_line_info_json(const tim::unwind::processed_entry& line_info_entry)
|
||||
{
|
||||
auto line_info = ::rocpd::json::create();
|
||||
line_info->set("line_address", as_hex(line_info_entry.line_address));
|
||||
line_info->set("name", std::string(demangle(line_info_entry.name)));
|
||||
|
||||
if(line_info_entry.lineinfo && !line_info_entry.lineinfo.lines.empty())
|
||||
{
|
||||
auto _lines = line_info_entry.lineinfo.lines;
|
||||
std::reverse(_lines.begin(), _lines.end());
|
||||
for(const auto& line : _lines)
|
||||
{
|
||||
auto inlined = ::rocpd::json::create();
|
||||
inlined->set("name", std::string(demangle(line.name)));
|
||||
inlined->set("location", std::string(line.location));
|
||||
inlined->set("line", std::to_string(line.line));
|
||||
line_info->set("inlined", inlined);
|
||||
}
|
||||
}
|
||||
|
||||
return line_info->to_string();
|
||||
}
|
||||
|
||||
std::string
|
||||
generate_hw_counter_json(int64_t _tid, const backtrace_metrics& metrics)
|
||||
{
|
||||
auto extdata = ::rocpd::json::create();
|
||||
|
||||
if(!metrics.get_hw_counters().empty())
|
||||
{
|
||||
auto _labels = backtrace_metrics::get_hw_counter_labels(_tid);
|
||||
auto _hw_cnt_vals = metrics.get_hw_counters();
|
||||
|
||||
auto hw_counters = ::rocpd::json::create();
|
||||
for(size_t i = 0; i < _labels.size(); ++i)
|
||||
{
|
||||
hw_counters->set(_labels.at(i), _hw_cnt_vals.at(i));
|
||||
}
|
||||
|
||||
extdata->set("hw_counters", hw_counters);
|
||||
}
|
||||
|
||||
return extdata->to_string();
|
||||
}
|
||||
|
||||
rocpd::data_processor&
|
||||
get_data_processor()
|
||||
{
|
||||
return rocpd::data_processor::get_instance();
|
||||
}
|
||||
|
||||
void
|
||||
rocpd_initialize_sampling_category()
|
||||
{
|
||||
static bool _is_initialized = false;
|
||||
if(_is_initialized) return;
|
||||
|
||||
auto& data_processor = get_data_processor();
|
||||
data_processor.insert_category(ROCPROFSYS_CATEGORY_SAMPLING,
|
||||
trait::name<category::sampling>::value);
|
||||
data_processor.insert_category(ROCPROFSYS_CATEGORY_OVERFLOW_SAMPLING,
|
||||
trait::name<category::overflow_sampling>::value);
|
||||
data_processor.insert_category(ROCPROFSYS_CATEGORY_TIMER_SAMPLING,
|
||||
trait::name<category::timer_sampling>::value);
|
||||
|
||||
_is_initialized = true;
|
||||
}
|
||||
|
||||
size_t
|
||||
rocpd_initialize_thread_info(size_t tid)
|
||||
{
|
||||
const auto& _thread_info = thread_info::get(tid, SequentTID);
|
||||
ROCPROFSYS_CI_THROW(!_thread_info, "No valid thread info for tid=%li\n", tid);
|
||||
if(!_thread_info) return -1;
|
||||
|
||||
auto& data_processor = get_data_processor();
|
||||
auto& n_info = node_info::get_instance();
|
||||
|
||||
return data_processor.insert_thread_info(
|
||||
n_info.id, getppid(), getpid(), _thread_info->index_data->system_value,
|
||||
threading::get_thread_name().c_str(), _thread_info->get_start(),
|
||||
_thread_info->get_stop(), "{}");
|
||||
}
|
||||
|
||||
void
|
||||
rocpd_init_track(const char* track_name, int64_t tid)
|
||||
{
|
||||
auto& data_processor = get_data_processor();
|
||||
auto& n_info = node_info::get_instance();
|
||||
|
||||
data_processor.insert_track(track_name, n_info.id, getpid(), tid, "{}");
|
||||
}
|
||||
|
||||
template <typename Category>
|
||||
void
|
||||
rocpd_insert_region(size_t thread_id, size_t start_time, size_t end_time, size_t name_id,
|
||||
const char* track, const char* call_stack = "{}",
|
||||
const char* line_info = "{}", const char* extdata = "{}")
|
||||
{
|
||||
auto& data_processor = get_data_processor();
|
||||
auto& n_info = node_info::get_instance();
|
||||
|
||||
auto event_id = data_processor.insert_event(category_enum_id<Category>::value, 0, 0,
|
||||
0, call_stack, line_info, extdata);
|
||||
|
||||
data_processor.insert_region(n_info.id, getpid(), thread_id, start_time, end_time,
|
||||
name_id, event_id);
|
||||
data_processor.insert_sample(track, start_time, event_id);
|
||||
}
|
||||
|
||||
auto&
|
||||
get_sampler_allocators()
|
||||
{
|
||||
@@ -810,6 +943,10 @@ void
|
||||
post_process_timemory(int64_t, const std::vector<timer_sampling_data>&,
|
||||
const std::vector<overflow_sampling_data>&);
|
||||
|
||||
void
|
||||
post_process_rocpd(int64_t _tid, const std::vector<timer_sampling_data>& _timer_data,
|
||||
const std::vector<overflow_sampling_data>& _overflow_data);
|
||||
|
||||
auto static_strings = std::set<std::string>{};
|
||||
|
||||
} // namespace
|
||||
@@ -939,15 +1076,15 @@ post_process()
|
||||
|
||||
auto _raw_data = _sampler->get_data();
|
||||
auto _loaded_data = load_offload_buffer(i);
|
||||
for(auto litr : _loaded_data)
|
||||
for(auto line : _loaded_data)
|
||||
{
|
||||
while(!litr.is_empty())
|
||||
while(!line.is_empty())
|
||||
{
|
||||
auto _v = sampler_bundle_t{};
|
||||
litr.read(&_v);
|
||||
line.read(&_v);
|
||||
_raw_data.emplace_back(std::move(_v));
|
||||
}
|
||||
litr.destroy();
|
||||
line.destroy();
|
||||
}
|
||||
|
||||
ROCPROFSYS_VERBOSE(2 || get_debug_sampling(),
|
||||
@@ -988,6 +1125,7 @@ post_process()
|
||||
|
||||
if(get_use_perfetto()) post_process_perfetto(i, _timer_data, _overflow_data);
|
||||
if(get_use_timemory()) post_process_timemory(i, _timer_data, _overflow_data);
|
||||
if(get_use_rocpd()) post_process_rocpd(i, _timer_data, _overflow_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1205,13 +1343,13 @@ post_process_perfetto(int64_t _tid, const std::vector<timer_sampling_data>& _tim
|
||||
auto _lines = iitr.lineinfo.lines;
|
||||
std::reverse(_lines.begin(), _lines.end());
|
||||
size_t _n = 0;
|
||||
for(const auto& litr : _lines)
|
||||
for(const auto& line : _lines)
|
||||
{
|
||||
auto _label = JOIN('-', "lineinfo", _n++);
|
||||
tracing::add_perfetto_annotation(
|
||||
ctx, _label.c_str(),
|
||||
JOIN('@', demangle(litr.name),
|
||||
JOIN(':', litr.location, litr.line)));
|
||||
JOIN('@', demangle(line.name),
|
||||
JOIN(':', line.location, line.line)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1298,11 +1436,11 @@ post_process_perfetto(int64_t _tid, const std::vector<timer_sampling_data>& _tim
|
||||
auto _lines = iitr.lineinfo.lines;
|
||||
std::reverse(_lines.begin(), _lines.end());
|
||||
size_t _n = 0;
|
||||
for(const auto& litr : _lines)
|
||||
for(const auto& line : _lines)
|
||||
{
|
||||
const auto* _name =
|
||||
static_strings.emplace(demangle(litr.name)).first->c_str();
|
||||
auto _info = JOIN(':', litr.location, litr.line);
|
||||
static_strings.emplace(demangle(line.name)).first->c_str();
|
||||
auto _info = JOIN(':', line.location, line.line);
|
||||
tracing::push_perfetto_track(
|
||||
category::timer_sampling{}, _name, _track, _beg,
|
||||
[&](::perfetto::EventContext ctx) {
|
||||
@@ -1342,13 +1480,13 @@ post_process_perfetto(int64_t _tid, const std::vector<timer_sampling_data>& _tim
|
||||
auto _lines = iitr.lineinfo.lines;
|
||||
std::reverse(_lines.begin(), _lines.end());
|
||||
size_t _n = 0;
|
||||
for(const auto& litr : _lines)
|
||||
for(const auto& line : _lines)
|
||||
{
|
||||
auto _label = JOIN('-', "lineinfo", _n++);
|
||||
tracing::add_perfetto_annotation(
|
||||
ctx, _label.c_str(),
|
||||
JOIN('@', demangle(litr.name),
|
||||
JOIN(':', litr.location, litr.line)));
|
||||
JOIN('@', demangle(line.name),
|
||||
JOIN(':', line.location, line.line)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1540,6 +1678,189 @@ post_process_timemory(int64_t _tid, const std::vector<timer_sampling_data>& _tim
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rocpd_post_process_overflow_data(
|
||||
int64_t _tid, const std::vector<overflow_sampling_data>& _overflow_data)
|
||||
{
|
||||
auto& data_processor = get_data_processor();
|
||||
|
||||
const auto& _thread_info = thread_info::get(_tid, SequentTID);
|
||||
ROCPROFSYS_CI_THROW(!_thread_info, "No valid thread info for tid=%li\n", _tid);
|
||||
if(!_thread_info) return;
|
||||
|
||||
auto _overflow_event =
|
||||
get_setting_value<std::string>("ROCPROFSYS_SAMPLING_OVERFLOW_EVENT").value_or("");
|
||||
|
||||
if(!_overflow_event.empty() && !_overflow_data.empty())
|
||||
{
|
||||
auto _beg_ns = std::max(_overflow_data.front().m_beg, _thread_info->get_start());
|
||||
auto _end_ns = std::min(_overflow_data.back().m_end, _thread_info->get_stop());
|
||||
|
||||
const auto _overflow_prefix = std::string_view{ "PERF_COUNT_" };
|
||||
const auto _overflow_pos = _overflow_event.find(_overflow_prefix);
|
||||
if(_overflow_pos != std::string::npos)
|
||||
_overflow_event =
|
||||
_overflow_event.substr(_overflow_pos + _overflow_prefix.length());
|
||||
|
||||
const auto* _main_name =
|
||||
static_strings.emplace(join(" ", _overflow_event, "samples [rocprof-sys]"))
|
||||
.first->c_str();
|
||||
auto main_name_id = data_processor.insert_string(_main_name);
|
||||
|
||||
const auto& _track_name =
|
||||
JOIN(" ", "Thread", _thread_info->index_data->sequent_value, "Overflow",
|
||||
"(S)", _thread_info->index_data->system_value);
|
||||
|
||||
auto thread_idx = rocpd_initialize_thread_info(_tid);
|
||||
rocpd_init_track(_track_name.c_str(), thread_idx);
|
||||
rocpd_insert_region<category::overflow_sampling>(
|
||||
thread_idx, _beg_ns, _end_ns, main_name_id, _track_name.c_str());
|
||||
|
||||
for(const auto& itr : _overflow_data)
|
||||
{
|
||||
auto _beg = itr.m_beg;
|
||||
auto _end = itr.m_end;
|
||||
|
||||
if(!_thread_info->is_valid_lifetime({ _beg, _end })) continue;
|
||||
|
||||
for(const auto& iitr : itr.m_stack)
|
||||
{
|
||||
const auto* _name =
|
||||
static_strings.emplace(demangle(iitr.name)).first->c_str();
|
||||
auto name_id = data_processor.insert_string(_name);
|
||||
rocpd_insert_region<category::overflow_sampling>(
|
||||
thread_idx, _beg, _end, name_id, _track_name.c_str(),
|
||||
generate_call_stack_json(iitr).c_str(),
|
||||
generate_line_info_json(iitr).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rocpd_post_process_backtrace_metrics(int64_t _tid,
|
||||
const std::vector<timer_sampling_data>& _timer_data)
|
||||
{
|
||||
auto _valid_metrics = backtrace_metrics::valid_array_t{};
|
||||
|
||||
for(const auto& itr : _timer_data)
|
||||
{
|
||||
_valid_metrics |= itr.m_metrics.get_valid();
|
||||
}
|
||||
|
||||
if(trait::runtime_enabled<backtrace_metrics>::get() && get_use_rocpd())
|
||||
{
|
||||
ROCPROFSYS_VERBOSE(3 || get_debug_sampling(),
|
||||
"[%li] Post-processing metrics for rocpd...\n", _tid);
|
||||
backtrace_metrics::init_rocpd(_tid, _valid_metrics);
|
||||
for(const auto& itr : _timer_data)
|
||||
itr.m_metrics.post_process_rocpd(_tid, 0.5 * (itr.m_beg + itr.m_end));
|
||||
backtrace_metrics::fini_rocpd(_tid, _valid_metrics);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rocpd_post_process_timer_data(int64_t _tid,
|
||||
const std::vector<timer_sampling_data>& _timer_data)
|
||||
{
|
||||
auto& data_processor = get_data_processor();
|
||||
|
||||
const auto& _thread_info = thread_info::get(_tid, SequentTID);
|
||||
ROCPROFSYS_CI_THROW(!_thread_info, "No valid thread info for tid=%li\n", _tid);
|
||||
if(!_thread_info) return;
|
||||
|
||||
if(!_timer_data.empty())
|
||||
{
|
||||
rocpd_post_process_backtrace_metrics(_tid, _timer_data);
|
||||
|
||||
auto _beg_ns = std::max(_timer_data.front().m_beg, _thread_info->get_start());
|
||||
auto _end_ns = std::min(_timer_data.back().m_end, _thread_info->get_stop());
|
||||
|
||||
const auto _track_name =
|
||||
JOIN(" ", "Thread", _thread_info->index_data->sequent_value, "(S)",
|
||||
_thread_info->index_data->system_value);
|
||||
|
||||
auto thread_idx = rocpd_initialize_thread_info(_tid);
|
||||
rocpd_init_track(_track_name.c_str(), thread_idx);
|
||||
const auto main_name_id = data_processor.insert_string("samples [rocprof-sys]");
|
||||
rocpd_insert_region<category::timer_sampling>(thread_idx, _beg_ns, _end_ns,
|
||||
main_name_id, _track_name.c_str());
|
||||
|
||||
auto _labels = backtrace_metrics::get_hw_counter_labels(_tid);
|
||||
for(const auto& itr : _timer_data)
|
||||
{
|
||||
size_t _ncount = 0;
|
||||
uint64_t _beg = itr.m_beg;
|
||||
uint64_t _end = itr.m_end;
|
||||
if(!_thread_info->is_valid_lifetime({ _beg, _end })) continue;
|
||||
|
||||
for(const auto& iitr : itr.m_stack)
|
||||
{
|
||||
auto _ncur = _ncount++;
|
||||
// the begin/end + HW counters will be same for entire call-stack so only
|
||||
// annotate the top and the bottom functons to keep the data consumption
|
||||
// low
|
||||
bool _include_common = (_ncur == 0 || _ncur + 1 == itr.m_stack.size());
|
||||
|
||||
// Only annotate HW counters when first or last and HW counters are not
|
||||
// empty
|
||||
bool _include_hw =
|
||||
_include_common && !itr.m_metrics.get_hw_counters().empty();
|
||||
|
||||
std::string hw_counter_json = "{}";
|
||||
if(_include_hw)
|
||||
{
|
||||
// current values when read
|
||||
hw_counter_json = generate_hw_counter_json(_tid, itr.m_metrics);
|
||||
}
|
||||
|
||||
if(get_sampling_include_inlines() && iitr.lineinfo)
|
||||
{
|
||||
auto _lines = iitr.lineinfo.lines;
|
||||
std::reverse(_lines.begin(), _lines.end());
|
||||
size_t _n = 0;
|
||||
for(const auto& line : _lines)
|
||||
{
|
||||
const auto* _name =
|
||||
static_strings.emplace(demangle(line.name)).first->c_str();
|
||||
auto inlined_name_id = data_processor.insert_string(_name);
|
||||
|
||||
auto inlined_call_stack = ::rocpd::json::create();
|
||||
inlined_call_stack->set("name", std::string(demangle(line.name)));
|
||||
inlined_call_stack->set("location", std::string(line.location));
|
||||
inlined_call_stack->set("line", std::to_string(line.line));
|
||||
inlined_call_stack->set("inlined", "true");
|
||||
|
||||
rocpd_insert_region<category::timer_sampling>(
|
||||
thread_idx, _beg, _end, inlined_name_id, _track_name.c_str(),
|
||||
inlined_call_stack->to_string().c_str(), "{}",
|
||||
// Only include HW counters for first inlined function
|
||||
(_n == 0) ? hw_counter_json.c_str() : "{}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto* _name = static_strings.emplace(iitr.name).first->c_str();
|
||||
const auto name_id = data_processor.insert_string(_name);
|
||||
rocpd_insert_region<category::timer_sampling>(
|
||||
thread_idx, _beg, _end, name_id, _track_name.c_str(),
|
||||
generate_call_stack_json(iitr).c_str(),
|
||||
generate_line_info_json(iitr).c_str(), hw_counter_json.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
post_process_rocpd(int64_t _tid, const std::vector<timer_sampling_data>& _timer_data,
|
||||
const std::vector<overflow_sampling_data>& _overflow_data)
|
||||
{
|
||||
rocpd_initialize_sampling_category();
|
||||
rocpd_post_process_overflow_data(_tid, _overflow_data);
|
||||
rocpd_post_process_timer_data(_tid, _timer_data);
|
||||
}
|
||||
|
||||
struct sampling_initialization
|
||||
{
|
||||
static void preinit()
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren