Change amd_smi and cpu_freq modules to use trace cache for rocpd (#690)
* Move amd-smi to use caching mechanism * Add VCN and JPEG activity to rocpd * Switch cpu_freq to use caching mechanism * Different approach with xcp activity & applied suggestions from code review * Applied suggestions from code review * Fix shadowing * Applied suggestions from code review
Цей коміт міститься в:
зафіксовано
GitHub
джерело
7601798fa7
коміт
96a46962ad
@@ -42,7 +42,7 @@ namespace trace_cache
|
||||
namespace
|
||||
{
|
||||
constexpr auto CACHE_FILE_FLUSH_TIMEOUT = 10ms;
|
||||
constexpr auto NUM_OF_THREADS = 1;
|
||||
constexpr auto NUM_OF_THREADS = 1;
|
||||
} // namespace
|
||||
|
||||
buffer_storage::buffer_storage(pid_t _pid)
|
||||
|
||||
+26
-13
@@ -26,6 +26,7 @@
|
||||
#include "PTL/ThreadPool.hh"
|
||||
#include "cache_utility.hpp"
|
||||
#include "sample_type.hpp"
|
||||
#include <PTL/PTL.hh>
|
||||
#include <cassert>
|
||||
#include <condition_variable>
|
||||
#include <cstdlib>
|
||||
@@ -37,7 +38,6 @@
|
||||
#include <string.h>
|
||||
#include <thread>
|
||||
#include <type_traits>
|
||||
#include <PTL/PTL.hh>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace rocprofsys
|
||||
@@ -63,7 +63,8 @@ public:
|
||||
|
||||
constexpr bool is_supported_type = (supported_types::is_supported<T> && ...);
|
||||
static_assert(is_supported_type, "Supported types are const char*, char*, "
|
||||
"unsigned long, unsigned int, and int.");
|
||||
"unsigned long, unsigned int, long, unsigned "
|
||||
"char, std::vector<unsigned char> and int.");
|
||||
|
||||
auto arg_size = get_size(values...);
|
||||
auto total_size = arg_size + sizeof(type) + sizeof(size_t);
|
||||
@@ -79,6 +80,13 @@ public:
|
||||
len = strlen(val) + 1;
|
||||
std::memcpy(dest, val, len);
|
||||
}
|
||||
else if constexpr(std::is_same_v<std::decay_t<Type>, std::vector<uint8_t>>)
|
||||
{
|
||||
size_t elem_count = val.size();
|
||||
len = elem_count + sizeof(size_t);
|
||||
std::memcpy(dest, &elem_count, sizeof(size_t));
|
||||
std::memcpy(dest + sizeof(size_t), val.data(), val.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
using ClearType = std::decay_t<decltype(val)>;
|
||||
@@ -110,7 +118,8 @@ private:
|
||||
(std::is_same_v<std::decay_t<T>, Types> || ...);
|
||||
};
|
||||
|
||||
using supported_types = typelist<const char*, char*, uint64_t, int32_t, uint32_t>;
|
||||
using supported_types = typelist<const char*, char*, uint64_t, int32_t, uint32_t,
|
||||
std::vector<uint8_t>, uint8_t, int64_t>;
|
||||
|
||||
template <typename T>
|
||||
static constexpr bool is_string_literal_v =
|
||||
@@ -129,6 +138,10 @@ private:
|
||||
}
|
||||
return ++size;
|
||||
}
|
||||
else if constexpr(std::is_same_v<std::decay_t<T>, std::vector<uint8_t>>)
|
||||
{
|
||||
return val.size() + sizeof(size_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
return sizeof(T);
|
||||
@@ -144,18 +157,18 @@ private:
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex m_mutex;
|
||||
std::condition_variable m_exit_condition;
|
||||
bool m_exit_finished{ false };
|
||||
bool m_running{ true };
|
||||
std::condition_variable m_shutdown_condition;
|
||||
std::mutex m_mutex;
|
||||
std::condition_variable m_exit_condition;
|
||||
bool m_exit_finished{ false };
|
||||
bool m_running{ true };
|
||||
std::condition_variable m_shutdown_condition;
|
||||
|
||||
std::unique_ptr<PTL::ThreadPool>m_thread_pool;
|
||||
std::unique_ptr<PTL::ThreadPool> m_thread_pool;
|
||||
std::unique_ptr<PTL::TaskGroup<void>> m_task_group;
|
||||
size_t m_head{ 0 };
|
||||
size_t m_tail{ 0 };
|
||||
std::unique_ptr<buffer_array_t> m_buffer{ std::make_unique<buffer_array_t>() };
|
||||
pid_t m_created_process;
|
||||
size_t m_head{ 0 };
|
||||
size_t m_tail{ 0 };
|
||||
std::unique_ptr<buffer_array_t> m_buffer{ std::make_unique<buffer_array_t>() };
|
||||
pid_t m_created_process;
|
||||
};
|
||||
|
||||
} // namespace trace_cache
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "common/synchronized.hpp"
|
||||
#include "core/agent.hpp"
|
||||
#include "core/categories.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
@@ -35,6 +36,7 @@
|
||||
# include <rocprofiler-sdk/cxx/name_info.hpp>
|
||||
#endif
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
@@ -53,6 +55,19 @@ struct process
|
||||
pid_t ppid;
|
||||
std::string command;
|
||||
};
|
||||
|
||||
template <typename Category>
|
||||
inline std::string
|
||||
annotate_category(std::optional<int> first_section = std::nullopt,
|
||||
std::optional<int> second_section = std::nullopt)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::string(tim::trait::name<Category>::value);
|
||||
if(first_section) ss << "_" << std::to_string(*first_section);
|
||||
if(second_section) ss << "_" << std::to_string(*second_section);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
struct pmc
|
||||
{
|
||||
agent_type type;
|
||||
@@ -108,6 +123,20 @@ struct thread
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Category>
|
||||
inline std::string
|
||||
annotate_with_device_id(uint32_t device_id,
|
||||
std::optional<int> first_section = std::nullopt,
|
||||
std::optional<int> second_section = std::nullopt)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::string(tim::trait::name<Category>::value) + " [" +
|
||||
std::to_string(device_id) + "]";
|
||||
if(first_section) ss << "_" << std::to_string(*first_section);
|
||||
if(second_section) ss << "_" << std::to_string(*second_section);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
struct track
|
||||
{
|
||||
std::string track_name; // < Unique
|
||||
|
||||
+264
@@ -33,6 +33,7 @@
|
||||
#include "trace_cache/storage_parser.hpp"
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <timemory/utility/demangle.hpp>
|
||||
@@ -375,6 +376,265 @@ rocpd_post_processing::get_pmc_event_with_sample_callback() const
|
||||
};
|
||||
}
|
||||
|
||||
postprocessing_callback
|
||||
rocpd_post_processing::get_amd_smi_sample_callback() const
|
||||
{
|
||||
struct xcp_metrics_t
|
||||
{
|
||||
std::vector<uint16_t> vcn_busy;
|
||||
std::vector<uint16_t> jpeg_busy;
|
||||
};
|
||||
|
||||
auto deserialize_xcp_metrics = [](const std::vector<uint8_t>& serialized_data,
|
||||
bool& _is_vcn_supported, bool& _is_jpeg_supported,
|
||||
std::vector<xcp_metrics_t>& result) {
|
||||
if(serialized_data.size() < 5)
|
||||
{
|
||||
throw std::runtime_error("Invalid serialized data: insufficient header size");
|
||||
}
|
||||
|
||||
size_t offset = 0;
|
||||
|
||||
// Read header
|
||||
_is_vcn_supported = static_cast<bool>(serialized_data[offset++]);
|
||||
_is_jpeg_supported = static_cast<bool>(serialized_data[offset++]);
|
||||
uint8_t chunk_count = serialized_data[offset++];
|
||||
uint8_t vcn_count = serialized_data[offset++];
|
||||
uint8_t jpeg_count = serialized_data[offset++];
|
||||
|
||||
constexpr size_t elem_size = sizeof(uint16_t) / sizeof(uint8_t);
|
||||
const size_t chunk_size = (vcn_count + jpeg_count) * elem_size;
|
||||
|
||||
// Validate total size
|
||||
const size_t expected_size = 5 + (chunk_count * chunk_size);
|
||||
if(serialized_data.size() != expected_size)
|
||||
{
|
||||
throw std::runtime_error("Invalid serialized data: size mismatch");
|
||||
}
|
||||
|
||||
auto deserialize_uint16_array = [](const std::vector<uint8_t>& data,
|
||||
size_t& _offset, int array_size) {
|
||||
std::vector<uint16_t> _result;
|
||||
_result.reserve(array_size);
|
||||
|
||||
for(int i = 0; i < array_size; ++i)
|
||||
{
|
||||
if(_offset + 1 >= data.size())
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"Invalid serialized data: unexpected end of data");
|
||||
}
|
||||
|
||||
uint16_t value = static_cast<uint16_t>(data[_offset]) |
|
||||
(static_cast<uint16_t>(data[_offset + 1]) << 8);
|
||||
_result.push_back(value);
|
||||
_offset += 2;
|
||||
}
|
||||
|
||||
return _result;
|
||||
};
|
||||
|
||||
result.reserve(chunk_count);
|
||||
|
||||
for(size_t count = 0; count < chunk_count; ++count)
|
||||
{
|
||||
xcp_metrics_t entry;
|
||||
entry.vcn_busy = deserialize_uint16_array(serialized_data, offset, vcn_count);
|
||||
entry.jpeg_busy =
|
||||
deserialize_uint16_array(serialized_data, offset, jpeg_count);
|
||||
|
||||
result.emplace_back(std::move(entry));
|
||||
}
|
||||
};
|
||||
|
||||
return [&](const storage_parsed_type_base& parsed) {
|
||||
auto _amd_smi = static_cast<const struct amd_smi_sample&>(parsed);
|
||||
|
||||
auto& data_processor = get_data_processor();
|
||||
|
||||
const auto* _name = trait::name<category::amd_smi>::value;
|
||||
auto name_primary_key = data_processor.insert_string(_name);
|
||||
auto event_id = data_processor.insert_event(name_primary_key, 0, 0, 0);
|
||||
|
||||
auto& _agent_manager = agent_manager::get_instance();
|
||||
auto base_id =
|
||||
_agent_manager.get_agent_by_type_index(_amd_smi.device_id, agent_type::GPU)
|
||||
.base_id;
|
||||
|
||||
auto insert_event_and_sample = [&](bool enabled, const char* pmc_name,
|
||||
const char* track_name, double value) {
|
||||
if(!enabled) return;
|
||||
data_processor.insert_pmc_event(event_id, base_id, pmc_name, value);
|
||||
data_processor.insert_sample(track_name, _amd_smi.timestamp, event_id);
|
||||
};
|
||||
|
||||
using pos = trace_cache::amd_smi_sample::settings_positions;
|
||||
std::bitset<8> settings_bits(_amd_smi.settings);
|
||||
bool is_busy_enabled = settings_bits.test(static_cast<int>(pos::busy));
|
||||
bool is_temp_enabled = settings_bits.test(static_cast<int>(pos::temp));
|
||||
bool is_power_enabled = settings_bits.test(static_cast<int>(pos::power));
|
||||
bool is_mem_usage_enabled = settings_bits.test(static_cast<int>(pos::mem_usage));
|
||||
|
||||
bool is_vcn_enabled = settings_bits.test(static_cast<int>(pos::vcn_activity));
|
||||
bool is_jpeg_enabled = settings_bits.test(static_cast<int>(pos::jpeg_activity));
|
||||
|
||||
insert_event_and_sample(
|
||||
is_busy_enabled, trait::name<category::amd_smi_gfx_busy>::value,
|
||||
info::annotate_with_device_id<category::amd_smi_gfx_busy>(_amd_smi.device_id)
|
||||
.c_str(),
|
||||
_amd_smi.gfx_activity);
|
||||
insert_event_and_sample(
|
||||
is_busy_enabled, trait::name<category::amd_smi_umc_busy>::value,
|
||||
info::annotate_with_device_id<category::amd_smi_umc_busy>(_amd_smi.device_id)
|
||||
.c_str(),
|
||||
_amd_smi.umc_activity);
|
||||
insert_event_and_sample(
|
||||
is_busy_enabled, trait::name<category::amd_smi_mm_busy>::value,
|
||||
info::annotate_with_device_id<category::amd_smi_mm_busy>(_amd_smi.device_id)
|
||||
.c_str(),
|
||||
_amd_smi.mm_activity);
|
||||
insert_event_and_sample(
|
||||
is_temp_enabled, trait::name<category::amd_smi_temp>::value,
|
||||
info::annotate_with_device_id<category::amd_smi_temp>(_amd_smi.device_id)
|
||||
.c_str(),
|
||||
_amd_smi.temperature);
|
||||
|
||||
insert_event_and_sample(
|
||||
is_power_enabled, trait::name<category::amd_smi_power>::value,
|
||||
info::annotate_with_device_id<category::amd_smi_power>(_amd_smi.device_id)
|
||||
.c_str(),
|
||||
_amd_smi.power);
|
||||
insert_event_and_sample(
|
||||
is_mem_usage_enabled, trait::name<category::amd_smi_memory_usage>::value,
|
||||
info::annotate_with_device_id<category::amd_smi_memory_usage>(
|
||||
_amd_smi.device_id)
|
||||
.c_str(),
|
||||
_amd_smi.mem_usage);
|
||||
|
||||
if(!is_vcn_enabled && !is_jpeg_enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<xcp_metrics_t> xcp_metrics;
|
||||
bool is_vcn_activity_supported;
|
||||
bool is_jpeg_activity_supported;
|
||||
deserialize_xcp_metrics(_amd_smi.xcp_activity, is_vcn_activity_supported,
|
||||
is_jpeg_activity_supported, xcp_metrics);
|
||||
|
||||
auto insert_xcp_metrics = [&](auto category, bool _is_enabled,
|
||||
const std::vector<uint16_t>& data,
|
||||
std::optional<size_t> _idx = std::nullopt) {
|
||||
if(!_is_enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using Category = std::decay_t<decltype(category)>;
|
||||
|
||||
for(size_t clk = 0; clk < data.size(); ++clk)
|
||||
{
|
||||
const auto value = data[clk];
|
||||
if(value == std::numeric_limits<uint16_t>::max())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto pmc_name = info::annotate_category<Category>(_idx, clk);
|
||||
auto track_name = info::annotate_with_device_id<Category>(
|
||||
_amd_smi.device_id, _idx, clk);
|
||||
|
||||
insert_event_and_sample(_is_enabled, pmc_name.c_str(), track_name.c_str(),
|
||||
value);
|
||||
}
|
||||
};
|
||||
|
||||
for(size_t idx = 0; idx < xcp_metrics.size(); ++idx)
|
||||
{
|
||||
auto dimension =
|
||||
xcp_metrics.size() == 1 ? std::nullopt : std::make_optional<size_t>(idx);
|
||||
|
||||
insert_xcp_metrics(category::amd_smi_vcn_activity{}, is_vcn_enabled,
|
||||
xcp_metrics[idx].vcn_busy, dimension);
|
||||
|
||||
insert_xcp_metrics(category::amd_smi_jpeg_activity{}, is_jpeg_enabled,
|
||||
xcp_metrics[idx].jpeg_busy, dimension);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
postprocessing_callback
|
||||
rocpd_post_processing::get_cpu_freq_sample_callback() const
|
||||
{
|
||||
struct core_freq_sample
|
||||
{
|
||||
size_t id;
|
||||
float value;
|
||||
};
|
||||
|
||||
auto deserialize_freqs = [](std::vector<uint8_t>& buffer) {
|
||||
std::vector<core_freq_sample> result;
|
||||
size_t offset = 0;
|
||||
|
||||
while(offset + sizeof(float) + sizeof(size_t) <= buffer.size())
|
||||
{
|
||||
core_freq_sample core_sample;
|
||||
std::memcpy(&core_sample.id, buffer.data() + offset, sizeof(size_t));
|
||||
offset += sizeof(size_t);
|
||||
std::memcpy(&core_sample.value, buffer.data() + offset, sizeof(float));
|
||||
offset += sizeof(float);
|
||||
result.push_back(core_sample);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
return [&](const storage_parsed_type_base& parsed) {
|
||||
auto _cpu_freq_sample = static_cast<const struct cpu_freq_sample&>(parsed);
|
||||
|
||||
auto& data_processor = get_data_processor();
|
||||
const auto* _name = trait::name<category::cpu_freq>::value;
|
||||
auto name_primary_key = data_processor.insert_string(_name);
|
||||
auto event_id = data_processor.insert_event(name_primary_key, 0, 0, 0);
|
||||
|
||||
auto device_id = 0;
|
||||
|
||||
auto& agent_mngr = agent_manager::get_instance();
|
||||
auto base_id =
|
||||
agent_mngr.get_agent_by_type_index(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, _cpu_freq_sample.timestamp, event_id);
|
||||
};
|
||||
|
||||
insert_event_and_sample(trait::name<category::process_page>::value,
|
||||
_cpu_freq_sample.page_rss);
|
||||
insert_event_and_sample(trait::name<category::process_virt>::value,
|
||||
_cpu_freq_sample.virt_mem_usage);
|
||||
insert_event_and_sample(trait::name<category::process_peak>::value,
|
||||
_cpu_freq_sample.peak_rss);
|
||||
insert_event_and_sample(trait::name<category::process_context_switch>::value,
|
||||
_cpu_freq_sample.context_switch_count);
|
||||
insert_event_and_sample(trait::name<category::process_page_fault>::value,
|
||||
_cpu_freq_sample.page_faults);
|
||||
insert_event_and_sample(trait::name<category::process_user_mode_time>::value,
|
||||
_cpu_freq_sample.user_mode_time);
|
||||
insert_event_and_sample(trait::name<category::process_kernel_mode_time>::value,
|
||||
_cpu_freq_sample.kernel_mode_time);
|
||||
|
||||
auto get_track_name = [](const auto& cpu_id) {
|
||||
return std::string(trait::name<category::cpu_freq>::value) + " [" +
|
||||
std::to_string(cpu_id) + "]";
|
||||
};
|
||||
|
||||
auto core_freq_samples = deserialize_freqs(_cpu_freq_sample.freqs);
|
||||
for(const auto& core : core_freq_samples)
|
||||
{
|
||||
insert_event_and_sample(get_track_name(core.id).c_str(), core.value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
rocpd_post_processing::rocpd_post_processing(metadata_registry& md)
|
||||
: m_metadata(md)
|
||||
{}
|
||||
@@ -399,6 +659,10 @@ rocpd_post_processing::register_parser_callback([[maybe_unused]] storage_parser&
|
||||
get_in_time_sample_callback());
|
||||
parser.register_type_callback(entry_type::pmc_event_with_sample,
|
||||
get_pmc_event_with_sample_callback());
|
||||
parser.register_type_callback(entry_type::amd_smi_sample,
|
||||
get_amd_smi_sample_callback());
|
||||
parser.register_type_callback(entry_type::cpu_freq_sample,
|
||||
get_cpu_freq_sample_callback());
|
||||
ROCPROFSYS_DEBUG("Buffer parser callbacks are registered..");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -52,6 +52,8 @@ private:
|
||||
postprocessing_callback get_region_callback() const;
|
||||
postprocessing_callback get_in_time_sample_callback() const;
|
||||
postprocessing_callback get_pmc_event_with_sample_callback() const;
|
||||
postprocessing_callback get_amd_smi_sample_callback() const;
|
||||
postprocessing_callback get_cpu_freq_sample_callback() const;
|
||||
|
||||
metadata_registry& m_metadata;
|
||||
};
|
||||
|
||||
@@ -21,10 +21,13 @@
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#if ROCPROFSYS_USE_ROCM > 0
|
||||
# include <rocprofiler-sdk/version.h>
|
||||
@@ -182,6 +185,43 @@ struct pmc_event_with_sample : in_time_sample
|
||||
size_t value;
|
||||
};
|
||||
|
||||
struct amd_smi_sample : storage_parsed_type_base
|
||||
{
|
||||
enum class settings_positions : uint8_t
|
||||
{
|
||||
busy = 0,
|
||||
temp,
|
||||
power,
|
||||
mem_usage,
|
||||
vcn_activity,
|
||||
jpeg_activity
|
||||
};
|
||||
|
||||
uint64_t settings; // bitfield
|
||||
uint32_t device_id;
|
||||
size_t timestamp;
|
||||
uint32_t gfx_activity;
|
||||
uint32_t umc_activity;
|
||||
uint32_t mm_activity;
|
||||
uint32_t power;
|
||||
int64_t temperature;
|
||||
size_t mem_usage;
|
||||
std::vector<uint8_t> xcp_activity;
|
||||
};
|
||||
|
||||
struct cpu_freq_sample : storage_parsed_type_base
|
||||
{
|
||||
size_t timestamp;
|
||||
int64_t page_rss;
|
||||
int64_t virt_mem_usage;
|
||||
int64_t peak_rss;
|
||||
int64_t context_switch_count;
|
||||
int64_t page_faults;
|
||||
int64_t user_mode_time;
|
||||
int64_t kernel_mode_time;
|
||||
std::vector<uint8_t> freqs;
|
||||
};
|
||||
|
||||
enum class entry_type : uint32_t
|
||||
{
|
||||
in_time_sample = 0x0000,
|
||||
@@ -192,6 +232,8 @@ enum class entry_type : uint32_t
|
||||
#if(ROCPROFSYS_USE_ROCM && ROCPROFILER_VERSION >= 600)
|
||||
memory_alloc = 0x0005,
|
||||
#endif
|
||||
amd_smi_sample = 0x0006,
|
||||
cpu_freq_sample = 0x0007,
|
||||
fragmented_space = 0xFFFF
|
||||
};
|
||||
} // namespace trace_cache
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "storage_parser.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "trace_cache/sample_type.hpp"
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
@@ -201,6 +202,30 @@ storage_parser::consume_storage()
|
||||
invoke_callbacks(header.type, _pmc_event_with_sample);
|
||||
break;
|
||||
}
|
||||
case entry_type::amd_smi_sample:
|
||||
{
|
||||
amd_smi_sample _amd_smi_sample;
|
||||
parse_data(sample.data(), _amd_smi_sample.settings,
|
||||
_amd_smi_sample.device_id, _amd_smi_sample.timestamp,
|
||||
_amd_smi_sample.gfx_activity, _amd_smi_sample.umc_activity,
|
||||
_amd_smi_sample.mm_activity, _amd_smi_sample.power,
|
||||
_amd_smi_sample.temperature, _amd_smi_sample.mem_usage,
|
||||
_amd_smi_sample.xcp_activity);
|
||||
invoke_callbacks(header.type, _amd_smi_sample);
|
||||
break;
|
||||
}
|
||||
case entry_type::cpu_freq_sample:
|
||||
{
|
||||
cpu_freq_sample _cpu_freq_sample;
|
||||
parse_data(sample.data(), _cpu_freq_sample.timestamp,
|
||||
_cpu_freq_sample.page_rss, _cpu_freq_sample.virt_mem_usage,
|
||||
_cpu_freq_sample.peak_rss,
|
||||
_cpu_freq_sample.context_switch_count,
|
||||
_cpu_freq_sample.page_faults, _cpu_freq_sample.user_mode_time,
|
||||
_cpu_freq_sample.kernel_mode_time, _cpu_freq_sample.freqs);
|
||||
invoke_callbacks(header.type, _cpu_freq_sample);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <rocprofiler-systems/categories.h>
|
||||
#include <stdint.h>
|
||||
@@ -60,6 +61,14 @@ private:
|
||||
arg = std::string((const char*) data_pos);
|
||||
data_pos += arg.size() + 1;
|
||||
}
|
||||
else if constexpr(std::is_same_v<T, std::vector<uint8_t>>)
|
||||
{
|
||||
size_t vector_size = *reinterpret_cast<const size_t*>(data_pos);
|
||||
data_pos += sizeof(size_t);
|
||||
arg.reserve(vector_size);
|
||||
std::copy_n(data_pos, vector_size, std::back_inserter(arg));
|
||||
data_pos += vector_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
arg = *reinterpret_cast<const T*>(data_pos);
|
||||
|
||||
@@ -29,11 +29,13 @@
|
||||
#include "core/agent.hpp"
|
||||
#include "core/trace_cache/cache_manager.hpp"
|
||||
#include "core/trace_cache/cache_utility.hpp"
|
||||
#include "core/trace_cache/sample_type.hpp"
|
||||
#include <amd_smi/amdsmi.h>
|
||||
#include <cstdint>
|
||||
#if defined(NDEBUG)
|
||||
# undef NDEBUG
|
||||
#endif
|
||||
|
||||
#include "core/agent_manager.hpp"
|
||||
#include "core/common.hpp"
|
||||
#include "core/components/fwd.hpp"
|
||||
#include "core/config.hpp"
|
||||
@@ -41,7 +43,6 @@
|
||||
#include "core/gpu.hpp"
|
||||
#include "core/node_info.hpp"
|
||||
#include "core/perfetto.hpp"
|
||||
#include "core/rocpd/data_processor.hpp"
|
||||
#include "core/state.hpp"
|
||||
#include "core/trace_cache/metadata_registry.hpp"
|
||||
#include "library/amd_smi.hpp"
|
||||
@@ -74,19 +75,6 @@ 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
|
||||
metadata_initialize_category()
|
||||
{
|
||||
@@ -95,18 +83,73 @@ metadata_initialize_category()
|
||||
}
|
||||
|
||||
void
|
||||
metadata_initialize_smi_tracks()
|
||||
metadata_initialize_smi_tracks(size_t gpu_id)
|
||||
{
|
||||
const auto thread_id = std::nullopt;
|
||||
|
||||
trace_cache::get_metadata_registry().add_track(
|
||||
{ trait::name<category::amd_smi_mm_busy>::value, thread_id, "{}" });
|
||||
{ trace_cache::info::annotate_with_device_id<category::amd_smi_gfx_busy>(gpu_id),
|
||||
thread_id, "{}" });
|
||||
trace_cache::get_metadata_registry().add_track(
|
||||
{ trait::name<category::amd_smi_power>::value, thread_id, "{}" });
|
||||
{ trace_cache::info::annotate_with_device_id<category::amd_smi_umc_busy>(gpu_id),
|
||||
thread_id, "{}" });
|
||||
trace_cache::get_metadata_registry().add_track(
|
||||
{ trait::name<category::amd_smi_temp>::value, thread_id, "{}" });
|
||||
{ trace_cache::info::annotate_with_device_id<category::amd_smi_mm_busy>(gpu_id),
|
||||
thread_id, "{}" });
|
||||
trace_cache::get_metadata_registry().add_track(
|
||||
{ trait::name<category::amd_smi_memory_usage>::value, thread_id, "{}" });
|
||||
{ trace_cache::info::annotate_with_device_id<category::amd_smi_power>(gpu_id),
|
||||
thread_id, "{}" });
|
||||
trace_cache::get_metadata_registry().add_track(
|
||||
{ trace_cache::info::annotate_with_device_id<category::amd_smi_temp>(gpu_id),
|
||||
thread_id, "{}" });
|
||||
trace_cache::get_metadata_registry().add_track(
|
||||
{ trace_cache::info::annotate_with_device_id<category::amd_smi_memory_usage>(
|
||||
gpu_id),
|
||||
thread_id, "{}" });
|
||||
|
||||
auto add_vcn_track = [&](std::optional<int> xcp_idx) {
|
||||
for(auto clk = 0; clk < AMDSMI_MAX_NUM_VCN; ++clk)
|
||||
{
|
||||
auto name = trace_cache::info::annotate_with_device_id<
|
||||
category::amd_smi_vcn_activity>(gpu_id, xcp_idx, clk);
|
||||
trace_cache::get_metadata_registry().add_track(
|
||||
{ name.c_str(), thread_id, "{}" });
|
||||
}
|
||||
};
|
||||
|
||||
auto add_jpeg_track = [&](std::optional<int> xcp_idx) {
|
||||
for(auto clk = 0; clk < AMDSMI_MAX_NUM_JPEG; ++clk)
|
||||
{
|
||||
auto name = trace_cache::info::annotate_with_device_id<
|
||||
category::amd_smi_jpeg_activity>(gpu_id, xcp_idx, clk);
|
||||
trace_cache::get_metadata_registry().add_track(
|
||||
{ name.c_str(), thread_id, "{}" });
|
||||
}
|
||||
};
|
||||
|
||||
if(gpu::is_vcn_activity_supported(gpu_id))
|
||||
{
|
||||
add_vcn_track(std::nullopt);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int xcp = 0; xcp < AMDSMI_MAX_NUM_XCP; ++xcp)
|
||||
{
|
||||
add_vcn_track(xcp);
|
||||
}
|
||||
}
|
||||
|
||||
if(gpu::is_jpeg_activity_supported(gpu_id))
|
||||
{
|
||||
add_jpeg_track(std::nullopt);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(auto xcp = 0; xcp < AMDSMI_MAX_NUM_XCP; ++xcp)
|
||||
{
|
||||
add_jpeg_track(xcp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -125,7 +168,21 @@ metadata_initialize_smi_pmc(size_t gpu_id)
|
||||
|
||||
trace_cache::get_metadata_registry().add_pmc_info(
|
||||
{ agent_type::GPU, gpu_id, TARGET_ARCH, EVENT_CODE, INSTANCE_ID,
|
||||
trait::name<category::amd_smi_mm_busy>::value, "Busy",
|
||||
trait::name<category::amd_smi_gfx_busy>::value, "GFX Busy",
|
||||
trait::name<category::amd_smi_gfx_busy>::description, LONG_DESCRIPTION,
|
||||
COMPONENT, trace_cache::PERCENTAGE, rocprofsys::trace_cache::ABSOLUTE, BLOCK,
|
||||
EXPRESSION, 0, 0, "{}" });
|
||||
|
||||
trace_cache::get_metadata_registry().add_pmc_info(
|
||||
{ agent_type::GPU, gpu_id, TARGET_ARCH, EVENT_CODE, INSTANCE_ID,
|
||||
trait::name<category::amd_smi_umc_busy>::value, "UMC Busy",
|
||||
trait::name<category::amd_smi_umc_busy>::description, LONG_DESCRIPTION,
|
||||
COMPONENT, trace_cache::PERCENTAGE, rocprofsys::trace_cache::ABSOLUTE, BLOCK,
|
||||
EXPRESSION, 0, 0, "{}" });
|
||||
|
||||
trace_cache::get_metadata_registry().add_pmc_info(
|
||||
{ agent_type::GPU, gpu_id, TARGET_ARCH, EVENT_CODE, INSTANCE_ID,
|
||||
trait::name<category::amd_smi_mm_busy>::value, "MM Busy",
|
||||
trait::name<category::amd_smi_mm_busy>::description, LONG_DESCRIPTION,
|
||||
COMPONENT, trace_cache::PERCENTAGE, rocprofsys::trace_cache::ABSOLUTE, BLOCK,
|
||||
EXPRESSION, 0, 0, "{}" });
|
||||
@@ -148,39 +205,74 @@ metadata_initialize_smi_pmc(size_t gpu_id)
|
||||
trait::name<category::amd_smi_memory_usage>::description, LONG_DESCRIPTION,
|
||||
COMPONENT, tim::units::mem_repr(tim::units::megabyte),
|
||||
rocprofsys::trace_cache::ABSOLUTE, 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 add_vcn_pmc = [&](std::optional<int> xcp_idx) {
|
||||
for(int clk = 0; clk < AMDSMI_MAX_NUM_VCN; ++clk)
|
||||
{
|
||||
std::stringstream name_ss;
|
||||
name_ss << trait::name<category::amd_smi_vcn_activity>::value;
|
||||
if(xcp_idx) name_ss << "_" << *xcp_idx;
|
||||
name_ss << "_" << clk;
|
||||
|
||||
auto& data_processor = get_data_processor();
|
||||
std::stringstream symbol_ss;
|
||||
symbol_ss << "VcnAct";
|
||||
if(xcp_idx) symbol_ss << "_" << *xcp_idx;
|
||||
symbol_ss << "_" << clk;
|
||||
|
||||
const auto* _name = trait::name<category::amd_smi>::value;
|
||||
auto name_primary_key = data_processor.insert_string(_name);
|
||||
auto event_id = data_processor.insert_event(name_primary_key, 0, 0, 0);
|
||||
|
||||
auto& _agent_manager = agent_manager::get_instance();
|
||||
auto base_id =
|
||||
_agent_manager.get_agent_by_type_index(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);
|
||||
trace_cache::get_metadata_registry().add_pmc_info(
|
||||
{ agent_type::GPU, gpu_id, TARGET_ARCH, EVENT_CODE, INSTANCE_ID,
|
||||
name_ss.str(), symbol_ss.str(),
|
||||
trait::name<category::amd_smi_vcn_activity>::description,
|
||||
LONG_DESCRIPTION, COMPONENT, trace_cache::PERCENTAGE,
|
||||
rocprofsys::trace_cache::ABSOLUTE, BLOCK, EXPRESSION, 0, 0 });
|
||||
}
|
||||
};
|
||||
|
||||
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 add_jpeg_pmc = [&](std::optional<int> xcp_idx) {
|
||||
for(auto clk = 0; clk < AMDSMI_MAX_NUM_JPEG; ++clk)
|
||||
{
|
||||
std::stringstream name_ss;
|
||||
name_ss << trait::name<category::amd_smi_jpeg_activity>::value;
|
||||
if(xcp_idx) name_ss << "_" << *xcp_idx;
|
||||
name_ss << "_" << std::to_string(clk);
|
||||
|
||||
std::stringstream symbol_ss;
|
||||
symbol_ss << "JpegAct";
|
||||
if(xcp_idx) symbol_ss << "_" << *xcp_idx;
|
||||
symbol_ss << "_" << std::to_string(clk);
|
||||
|
||||
trace_cache::get_metadata_registry().add_pmc_info(
|
||||
{ agent_type::GPU, gpu_id, TARGET_ARCH, EVENT_CODE, INSTANCE_ID,
|
||||
name_ss.str(), symbol_ss.str(),
|
||||
trait::name<category::amd_smi_jpeg_activity>::description,
|
||||
LONG_DESCRIPTION, COMPONENT, trace_cache::PERCENTAGE,
|
||||
rocprofsys::trace_cache::ABSOLUTE, BLOCK, EXPRESSION, 0, 0 });
|
||||
}
|
||||
};
|
||||
|
||||
if(gpu::is_vcn_activity_supported(gpu_id))
|
||||
{
|
||||
add_vcn_pmc(std::nullopt);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int xcp = 0; xcp < AMDSMI_MAX_NUM_XCP; ++xcp)
|
||||
{
|
||||
add_vcn_pmc(xcp);
|
||||
}
|
||||
}
|
||||
|
||||
if(gpu::is_jpeg_activity_supported(gpu_id))
|
||||
{
|
||||
add_jpeg_pmc(std::nullopt);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(auto xcp = 0; xcp < AMDSMI_MAX_NUM_XCP; ++xcp)
|
||||
{
|
||||
add_jpeg_pmc(xcp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto&
|
||||
@@ -241,6 +333,101 @@ get_state()
|
||||
static std::atomic<State> _v{ State::PreInit };
|
||||
return _v;
|
||||
}
|
||||
|
||||
std::vector<uint8_t>
|
||||
serialize_xcp_metrics(const bool& use_vcn_activity, const bool& use_jpeg_activity,
|
||||
const amdsmi_gpu_metrics_t& gpu_metrics)
|
||||
{
|
||||
// Chunk:
|
||||
// <vcn_data_0>..<vcn_data_[vcn_count]> // lower and higher byte
|
||||
// <jpeg_data_0>..<jpeg_data_[jpeg_count]> // lower and higher byte
|
||||
|
||||
// Serialized:
|
||||
// <is_vcn_supported>
|
||||
// <is_jpeg_supported>
|
||||
// <xcp_count>
|
||||
// <vcn_count>
|
||||
// <jpeg_count>
|
||||
// Chunk_0
|
||||
// ...
|
||||
// Chunk_[xcp_count]
|
||||
|
||||
constexpr uint8_t vcn_count = AMDSMI_MAX_NUM_VCN;
|
||||
constexpr uint8_t jpeg_count = AMDSMI_MAX_NUM_JPEG;
|
||||
constexpr uint8_t xcp_count = AMDSMI_MAX_NUM_XCP;
|
||||
constexpr size_t elem_size = sizeof(uint16_t) / sizeof(uint8_t);
|
||||
constexpr uint8_t vector_size_header = sizeof(uint8_t);
|
||||
constexpr uint8_t serialized_data_headers =
|
||||
5 * vector_size_header; // is_vcn_supported + is_jpeg_supported + xcp_count +
|
||||
// vcn_count + jpeg_count
|
||||
constexpr size_t chunk_size = ((vcn_count + jpeg_count) * elem_size);
|
||||
|
||||
auto serialize_uint16_array = [](std::vector<uint8_t>& data, const uint16_t* arr,
|
||||
int array_size) {
|
||||
for(int i = 0; i < array_size; ++i)
|
||||
{
|
||||
data.push_back(static_cast<uint8_t>(arr[i] & 0xFF));
|
||||
data.push_back(static_cast<uint8_t>((arr[i] >> 8) & 0xFF));
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<uint8_t> result;
|
||||
|
||||
const bool is_vcn_jpeg_supported = (use_vcn_activity || use_jpeg_activity);
|
||||
const size_t chunk_count = is_vcn_jpeg_supported ? 1 : xcp_count;
|
||||
const size_t total_size = serialized_data_headers + (chunk_count * chunk_size);
|
||||
|
||||
result.reserve(total_size);
|
||||
|
||||
result.push_back((uint8_t) use_vcn_activity);
|
||||
result.push_back((uint8_t) use_jpeg_activity);
|
||||
result.push_back(chunk_count);
|
||||
result.push_back(vcn_count);
|
||||
result.push_back(jpeg_count);
|
||||
|
||||
for(size_t count = 0; count < chunk_count; ++count)
|
||||
{
|
||||
const auto* vcn_data =
|
||||
(is_vcn_jpeg_supported ? gpu_metrics.vcn_activity
|
||||
: gpu_metrics.xcp_stats[count].vcn_busy);
|
||||
const auto* jpeg_data =
|
||||
(is_vcn_jpeg_supported ? gpu_metrics.jpeg_activity
|
||||
: gpu_metrics.xcp_stats[count].jpeg_busy);
|
||||
|
||||
serialize_uint16_array(result, vcn_data, vcn_count);
|
||||
serialize_uint16_array(result, jpeg_data, jpeg_count);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t
|
||||
serialize_settings(uint32_t _device_id)
|
||||
{
|
||||
auto settings = get_settings(_device_id);
|
||||
std::bitset<8> settings_bits;
|
||||
settings_bits.reset();
|
||||
settings_bits.set(
|
||||
static_cast<int>(trace_cache::amd_smi_sample::settings_positions::busy),
|
||||
settings.busy);
|
||||
settings_bits.set(
|
||||
static_cast<int>(trace_cache::amd_smi_sample::settings_positions::temp),
|
||||
settings.temp);
|
||||
settings_bits.set(
|
||||
static_cast<int>(trace_cache::amd_smi_sample::settings_positions::power),
|
||||
settings.power);
|
||||
settings_bits.set(
|
||||
static_cast<int>(trace_cache::amd_smi_sample::settings_positions::mem_usage),
|
||||
settings.mem_usage);
|
||||
settings_bits.set(
|
||||
static_cast<int>(trace_cache::amd_smi_sample::settings_positions::vcn_activity),
|
||||
settings.vcn_activity);
|
||||
settings_bits.set(
|
||||
static_cast<int>(trace_cache::amd_smi_sample::settings_positions::jpeg_activity),
|
||||
settings.jpeg_activity);
|
||||
return settings_bits.to_ulong();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
@@ -252,12 +439,12 @@ std::unique_ptr<data::promise_t> data::polling_finished = {};
|
||||
data::data(uint32_t _dev_id) { sample(_dev_id); }
|
||||
|
||||
void
|
||||
data::sample(uint32_t _dev_id)
|
||||
data::sample(uint32_t _device_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());
|
||||
auto _timestamp = tim::get_clock_real_now<size_t, std::nano>();
|
||||
assert(_timestamp < std::numeric_limits<int64_t>::max());
|
||||
amdsmi_gpu_metrics_t _gpu_metrics;
|
||||
bool _vcn_or_jpeg_activity_enabled = false;
|
||||
|
||||
@@ -265,8 +452,8 @@ data::sample(uint32_t _dev_id)
|
||||
|
||||
if(_state != State::Active) return;
|
||||
|
||||
m_dev_id = _dev_id;
|
||||
m_ts = _ts;
|
||||
m_dev_id = _device_id;
|
||||
m_ts = _timestamp;
|
||||
|
||||
#define ROCPROFSYS_AMDSMI_GET(OPTION, FUNCTION, ...) \
|
||||
if(OPTION) \
|
||||
@@ -283,7 +470,7 @@ data::sample(uint32_t _dev_id)
|
||||
} \
|
||||
}
|
||||
|
||||
amdsmi_processor_handle sample_handle = gpu::get_handle_from_id(_dev_id);
|
||||
amdsmi_processor_handle sample_handle = gpu::get_handle_from_id(_device_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,
|
||||
@@ -354,8 +541,14 @@ data::sample(uint32_t _dev_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef ROCPROFSYS_AMDSMI_GET
|
||||
|
||||
trace_cache::get_buffer_storage().store(
|
||||
trace_cache::entry_type::amd_smi_sample, serialize_settings(m_dev_id), _device_id,
|
||||
_timestamp, m_busy_perc.gfx_activity, m_busy_perc.umc_activity,
|
||||
m_busy_perc.mm_activity, m_power.current_socket_power, m_temp, m_mem_usage,
|
||||
serialize_xcp_metrics(gpu::is_vcn_activity_supported(m_dev_id),
|
||||
gpu::is_jpeg_activity_supported(m_dev_id), _gpu_metrics));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -396,10 +589,10 @@ config()
|
||||
data::get_initial().at(itr).sample(itr);
|
||||
|
||||
metadata_initialize_category();
|
||||
metadata_initialize_smi_tracks();
|
||||
|
||||
for(const auto& _dev_id : data::device_list)
|
||||
{
|
||||
metadata_initialize_smi_tracks(_dev_id);
|
||||
metadata_initialize_smi_pmc(_dev_id);
|
||||
}
|
||||
}
|
||||
@@ -409,6 +602,9 @@ sample()
|
||||
{
|
||||
auto_lock_t _lk{ type_mutex<category::amd_smi>() };
|
||||
|
||||
// TODO: Reorganize amd_smi::data and sampling mechanism not to store same data in
|
||||
// bundle_data and in trace_cache
|
||||
|
||||
for(auto itr : data::device_list)
|
||||
{
|
||||
if(amd_smi::get_state() != State::Active) continue;
|
||||
@@ -486,7 +682,6 @@ data::post_process(uint32_t _dev_id)
|
||||
auto _settings = get_settings(_dev_id);
|
||||
|
||||
auto use_perfetto = get_use_perfetto();
|
||||
auto use_rocpd = get_use_rocpd();
|
||||
|
||||
for(auto& itr : _amd_smi)
|
||||
{
|
||||
@@ -661,12 +856,6 @@ data::post_process(uint32_t _dev_id)
|
||||
setup_perfetto_counter_tracks();
|
||||
write_perfetto_metrics();
|
||||
}
|
||||
|
||||
if(use_rocpd)
|
||||
{
|
||||
rocpd_process_smi_pmc_events(_dev_id, _settings, _ts, _mmbusy, _temp, _power,
|
||||
_usage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,9 +28,10 @@
|
||||
#include "core/debug.hpp"
|
||||
#include "core/node_info.hpp"
|
||||
#include "core/perfetto.hpp"
|
||||
#include "core/rocpd/data_processor.hpp"
|
||||
#include "core/timemory.hpp"
|
||||
#include "core/trace_cache/cache_manager.hpp"
|
||||
#include "core/trace_cache/metadata_registry.hpp"
|
||||
#include "core/trace_cache/sample_type.hpp"
|
||||
#include "library/components/cpu_freq.hpp"
|
||||
#include "library/thread_info.hpp"
|
||||
|
||||
@@ -42,10 +43,12 @@
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <sys/resource.h>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace rocprofsys
|
||||
{
|
||||
@@ -67,14 +70,6 @@ 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)
|
||||
@@ -86,12 +81,6 @@ do_for_enabled_cpus(Func&& func)
|
||||
}
|
||||
}
|
||||
|
||||
rocpd::data_processor&
|
||||
get_data_processor()
|
||||
{
|
||||
return rocpd::data_processor::get_instance();
|
||||
}
|
||||
|
||||
void
|
||||
metadata_initialize_cpu_freq_category()
|
||||
{
|
||||
@@ -104,8 +93,9 @@ metadata_initialize_cpu_freq_tracks()
|
||||
{
|
||||
do_for_enabled_cpus([&](size_t cpu_id) {
|
||||
trace_cache::get_metadata_registry().add_track(
|
||||
{ get_cpu_freq_track_name<category::cpu_freq>(cpu_id).c_str(), std::nullopt,
|
||||
"{}" });
|
||||
{ trace_cache::info::annotate_with_device_id<category::cpu_freq>(cpu_id)
|
||||
.c_str(),
|
||||
std::nullopt, "{}" });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -146,9 +136,10 @@ metadata_initialize_cpu_freq_pmc(size_t dev_id)
|
||||
do_for_enabled_cpus([&](size_t cpu_id) {
|
||||
trace_cache::get_metadata_registry().add_pmc_info(
|
||||
{ agent_type::CPU, dev_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(),
|
||||
trace_cache::info::annotate_with_device_id<category::cpu_freq>(cpu_id)
|
||||
.c_str(),
|
||||
"Frequency", trait::name<category::cpu_freq>::description, LONG_DESCRIPTION,
|
||||
COMPONENT, component::cpu_freq::display_unit().c_str(),
|
||||
rocprofsys::trace_cache::ABSOLUTE, BLOCK, EXPRESSION, 0, 0 });
|
||||
});
|
||||
|
||||
@@ -195,41 +186,27 @@ metadata_initialize_cpu_freq_pmc(size_t dev_id)
|
||||
COMPONENT, TIME, rocprofsys::trace_cache::ABSOLUTE, 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)
|
||||
std::vector<uint8_t>
|
||||
serialize_freqs(const component::cpu_freq& freq)
|
||||
{
|
||||
auto& data_processor = get_data_processor();
|
||||
const auto* _name = trait::name<category::cpu_freq>::value;
|
||||
auto name_primary_key = data_processor.insert_string(_name);
|
||||
auto event_id = data_processor.insert_event(name_primary_key, 0, 0, 0);
|
||||
constexpr size_t idx_elements = sizeof(size_t) / sizeof(uint8_t);
|
||||
constexpr size_t value_elements = sizeof(float) / sizeof(uint8_t);
|
||||
|
||||
auto& agent_mngr = agent_manager::get_instance();
|
||||
auto base_id = agent_mngr.get_agent_by_type_index(device_id, agent_type::CPU).base_id;
|
||||
std::vector<uint8_t> result;
|
||||
const auto enabled_cpus_size = component::cpu_freq::get_enabled_cpus().size();
|
||||
const auto result_size = enabled_cpus_size * (idx_elements + value_elements);
|
||||
result.resize(result_size);
|
||||
result.assign(result_size, 0);
|
||||
|
||||
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));
|
||||
size_t offset = 0;
|
||||
do_for_enabled_cpus([&](const auto& idx) {
|
||||
auto value = freq.at(idx);
|
||||
std::memcpy(result.data() + offset, &idx, sizeof(size_t));
|
||||
offset += sizeof(size_t);
|
||||
std::memcpy(result.data() + offset, &value, sizeof(float));
|
||||
offset += sizeof(float);
|
||||
});
|
||||
|
||||
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);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -251,9 +228,15 @@ setup()
|
||||
category::process_page_fault, category::process_user_mode_time,
|
||||
category::process_kernel_mode_time>{});
|
||||
}
|
||||
|
||||
metadata_initialize_cpu_freq_category();
|
||||
metadata_initialize_cpu_usage_tracks();
|
||||
}
|
||||
|
||||
void
|
||||
config()
|
||||
{
|
||||
component::cpu_freq::configure();
|
||||
|
||||
metadata_initialize_cpu_freq_tracks();
|
||||
|
||||
// `get_enabled_cpus()` returns the number of cores enabled for monitoring but
|
||||
@@ -268,23 +251,26 @@ setup()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
config()
|
||||
{
|
||||
component::cpu_freq::configure();
|
||||
}
|
||||
|
||||
void
|
||||
sample()
|
||||
{
|
||||
auto _ts = tim::get_clock_real_now<size_t, std::nano>();
|
||||
auto _timestamp = tim::get_clock_real_now<size_t, std::nano>();
|
||||
|
||||
auto _rcache = tim::rusage_cache{ RUSAGE_SELF };
|
||||
auto _freqs = component::cpu_freq{}.sample();
|
||||
|
||||
// user and kernel mode times are in microseconds
|
||||
trace_cache::get_buffer_storage().store(
|
||||
trace_cache::entry_type::cpu_freq_sample, _timestamp, tim::get_page_rss(),
|
||||
tim::get_virt_mem(), _rcache.get_peak_rss(),
|
||||
_rcache.get_num_priority_context_switch() +
|
||||
_rcache.get_num_voluntary_context_switch(),
|
||||
_rcache.get_num_major_page_faults() + _rcache.get_num_minor_page_faults(),
|
||||
_rcache.get_user_mode_time() * 1000, _rcache.get_kernel_mode_time() * 1000,
|
||||
serialize_freqs(_freqs));
|
||||
|
||||
data.emplace_back(
|
||||
_ts, tim::get_page_rss(), tim::get_virt_mem(), _rcache.get_peak_rss(),
|
||||
_timestamp, tim::get_page_rss(), tim::get_virt_mem(), _rcache.get_peak_rss(),
|
||||
_rcache.get_num_priority_context_switch() +
|
||||
_rcache.get_num_voluntary_context_switch(),
|
||||
_rcache.get_num_major_page_faults() + _rcache.get_num_minor_page_faults(),
|
||||
@@ -420,12 +406,6 @@ post_process()
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if(get_use_perfetto())
|
||||
|
||||
Посилання в новій задачі
Заблокувати користувача