PLAT-130886: Support for MI300 XCC modes for rocprofv2
1. Accumulated mode(default mode) will aggregate counters and metric values from all xcc.
2. Individual mode (export ROCPROFILER_INDIVIDUAL_XCC_MODE=1) will dump metrics from each xcc separately.
Change-Id: I18ca334514f626f0c8e92d1472c1738978baccd4
[ROCm/rocprofiler commit: 58c4b165fe]
Αυτή η υποβολή περιλαμβάνεται σε:
υποβλήθηκε από
Ammar ELWazir
γονέας
d9afb4322f
υποβολή
7e912d3a61
@@ -2,6 +2,7 @@
|
||||
#include "src/utils/helper.h"
|
||||
#include "src/core/hsa/hsa_common.h"
|
||||
#include <set>
|
||||
#include <math.h>
|
||||
|
||||
using namespace rocmtools;
|
||||
|
||||
@@ -25,6 +26,7 @@ struct block_status_t {
|
||||
typedef struct {
|
||||
std::vector<results_t*>* results;
|
||||
size_t index;
|
||||
uint32_t single_xcc_buff_size;
|
||||
} callback_data_t;
|
||||
|
||||
static inline bool IsEventMatch(const hsa_ven_amd_aqlprofile_event_t& event1,
|
||||
@@ -43,7 +45,9 @@ hsa_status_t pmcCallback(hsa_ven_amd_aqlprofile_info_type_t info_type,
|
||||
++data_it) {
|
||||
if (info_type == HSA_VEN_AMD_AQLPROFILE_INFO_PMC_DATA) {
|
||||
if (IsEventMatch(info_data->pmc_data.event, (*data_it)->event)) {
|
||||
(*data_it)->val_double += info_data->pmc_data.result; // TODO: += or =
|
||||
uint32_t xcc_index = floor(passed_data->index / passed_data->single_xcc_buff_size);
|
||||
(*data_it)->xcc_vals[xcc_index] += info_data->pmc_data.result; // stores event result from each xcc separately
|
||||
(*data_it)->val_double += info_data->pmc_data.result; // stores accumulated event result from all xccs
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,6 +91,7 @@ bool metrics::ExtractMetricEvents(
|
||||
results_list holds the result objects for each event (which means, basic counters only)
|
||||
*/
|
||||
try {
|
||||
uint32_t xcc_count = rocmtools::hsa_support::GetAgentInfo(gpu_agent.handle).getXccCount();
|
||||
for (size_t i = 0; i < metric_names.size(); i++) {
|
||||
counters_vec_t counters_vec;
|
||||
// TODO: saurabh
|
||||
@@ -102,7 +107,7 @@ bool metrics::ExtractMetricEvents(
|
||||
// adding result object for derived metric
|
||||
std::lock_guard<std::mutex> lock(extract_metric_events_lock);
|
||||
if (results_map.find(metric_names[i]) == results_map.end()) {
|
||||
results_map[metric_names[i]] = new results_t{metric_names[i], 0, {}};
|
||||
results_map[metric_names[i]] = new results_t(metric_names[i], {}, xcc_count);
|
||||
} // else {
|
||||
// continue;
|
||||
// }
|
||||
@@ -124,7 +129,7 @@ bool metrics::ExtractMetricEvents(
|
||||
} else {
|
||||
// result object for base metric
|
||||
// std::cout << "Metric : " << metric->GetName() << " : " << counter->name << std::endl;
|
||||
result = new results_t{counter->name, 0, {}}; // TODO: set correct initial value
|
||||
result = new results_t(counter->name, {}, xcc_count); // TODO: set correct initial value
|
||||
results_map[counter->name] = result;
|
||||
}
|
||||
} else {
|
||||
@@ -180,9 +185,11 @@ bool metrics::ExtractMetricEvents(
|
||||
}
|
||||
|
||||
|
||||
bool metrics::GetCounterData(hsa_ven_amd_aqlprofile_profile_t* profile,
|
||||
bool metrics::GetCounterData(hsa_ven_amd_aqlprofile_profile_t* profile, hsa_agent_t gpu_agent,
|
||||
std::vector<results_t*>& results_list) {
|
||||
callback_data_t callback_data{&results_list, 0};
|
||||
uint32_t xcc_count = rocmtools::hsa_support::GetAgentInfo(gpu_agent.handle).getXccCount();
|
||||
uint32_t single_xcc_buff_size = profile->output_buffer.size /(sizeof(uint64_t) * xcc_count);
|
||||
callback_data_t callback_data{&results_list, 0, single_xcc_buff_size};
|
||||
hsa_status_t status = hsa_ven_amd_aqlprofile_iterate_data(profile, pmcCallback, &callback_data);
|
||||
return (status == HSA_STATUS_SUCCESS);
|
||||
}
|
||||
@@ -202,3 +209,17 @@ bool metrics::GetMetricsData(std::map<std::string, results_t*>& results_map,
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void metrics::GetCountersAndMetricResultsByXcc(uint32_t xcc_index, std::vector<results_t*>& results_list,
|
||||
std::map<std::string, results_t*>& results_map,
|
||||
std::vector<const Metric*>& metrics_list){
|
||||
for(auto it = results_list.begin(); it != results_list.end(); it++){
|
||||
(*it)->val_double = (*it)->xcc_vals[xcc_index]; // set val_double to hold value for specific xcc
|
||||
}
|
||||
|
||||
for(auto it = results_map.begin(); it != results_map.end(); it++){
|
||||
it->second->val_double = it->second->xcc_vals[xcc_index]; // set val_double to hold value for specific xcc
|
||||
}
|
||||
|
||||
GetMetricsData(results_map, metrics_list);
|
||||
}
|
||||
|
||||
@@ -33,11 +33,20 @@ THE SOFTWARE.
|
||||
|
||||
namespace rocmtools {
|
||||
|
||||
typedef struct {
|
||||
typedef std::vector<double> xcc_results_t;
|
||||
|
||||
class results_t{
|
||||
public:
|
||||
results_t(std::string in_name, event_t in_event, uint32_t xcc_count):
|
||||
name(in_name), val_double(0), event(in_event) {
|
||||
xcc_vals.resize(xcc_count);
|
||||
std::fill(xcc_vals.begin(), xcc_vals.end(), 0);
|
||||
}
|
||||
std::string name;
|
||||
double val_double;
|
||||
xcc_results_t xcc_vals;
|
||||
event_t event;
|
||||
} results_t;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
packet_t* start_packet;
|
||||
@@ -62,12 +71,16 @@ bool ExtractMetricEvents(
|
||||
std::map<std::string, std::set<std::string>>& metrics_counters);
|
||||
|
||||
|
||||
bool GetCounterData(hsa_ven_amd_aqlprofile_profile_t* profile,
|
||||
bool GetCounterData(hsa_ven_amd_aqlprofile_profile_t* profile, hsa_agent_t gpu_agent,
|
||||
std::vector<results_t*>& results_list);
|
||||
|
||||
bool GetMetricsData(std::map<std::string, results_t*>& results_map,
|
||||
std::vector<const Metric*>& metrics_list);
|
||||
|
||||
void GetCountersAndMetricResultsByXcc(uint32_t xcc_index, std::vector<results_t*>& results_list,
|
||||
std::map<std::string, results_t*>& results_map,
|
||||
std::vector<const Metric*>& metrics_list);
|
||||
|
||||
} // namespace metrics
|
||||
} // namespace rocmtools
|
||||
|
||||
|
||||
@@ -84,6 +84,14 @@ AgentInfo::AgentInfo(const hsa_agent_t agent, ::CoreApiTable* table) : handle_(a
|
||||
{
|
||||
rocmtools::fatal("hsa_agent_get_info for PCI info failed");
|
||||
}
|
||||
|
||||
// TODO: (sauverma) use hsa_agent_get_info_fn(HSA_AMD_AGENT_INFO_NUM_XCC)
|
||||
// to get xcc_num once hsa headers are updated from rocr/hsa
|
||||
std::string gpu_name = std::string(name_).substr(0,6);
|
||||
if (gpu_name == "gfx940")
|
||||
xcc_num_ = 6;
|
||||
else
|
||||
xcc_num_ = 1;
|
||||
}
|
||||
|
||||
int AgentInfo::getIndex() const { return index_; }
|
||||
@@ -102,6 +110,7 @@ uint32_t AgentInfo::getCUCountPerSH() const { return compute_units_per_sh_; }
|
||||
uint32_t AgentInfo::getWaveSlotsPerSimd() const { return wave_slots_per_simd_; }
|
||||
uint32_t AgentInfo::getPCIDomain() const { return pci_domain_; }
|
||||
uint32_t AgentInfo::getPCILocationID() const { return pci_location_id_; }
|
||||
uint32_t AgentInfo::getXccCount() const { return xcc_num_; }
|
||||
|
||||
void AgentInfo::setIndex(int index) { index_ = index; }
|
||||
void AgentInfo::setType(hsa_device_type_t type) { type_ = type; }
|
||||
|
||||
@@ -59,6 +59,7 @@ class AgentInfo {
|
||||
uint32_t getWaveSlotsPerSimd() const;
|
||||
uint32_t getPCIDomain() const;
|
||||
uint32_t getPCILocationID() const;
|
||||
uint32_t getXccCount() const;
|
||||
|
||||
void setIndex(int index);
|
||||
void setType(hsa_device_type_t type);
|
||||
@@ -81,6 +82,8 @@ class AgentInfo {
|
||||
// CUs per SH/SA
|
||||
uint32_t compute_units_per_sh_;
|
||||
uint32_t wave_slots_per_simd_;
|
||||
// Number of XCCs on the GPU
|
||||
uint32_t xcc_num_;
|
||||
|
||||
uint32_t pci_domain_;
|
||||
uint32_t pci_location_id_;
|
||||
|
||||
@@ -290,9 +290,6 @@ hsa_status_t attTraceDataCallback(hsa_ven_amd_aqlprofile_info_type_t info_type,
|
||||
}
|
||||
|
||||
void AddRecordCounters(rocprofiler_record_profiler_t* record, const pending_signal_t& pending) {
|
||||
rocmtools::metrics::GetCounterData(pending.profile, pending.context->results_list);
|
||||
rocmtools::metrics::GetMetricsData(pending.context->results_map, pending.context->metrics_list);
|
||||
|
||||
std::vector<rocprofiler_record_counter_instance_t> counters_vec;
|
||||
for (size_t i = 0; i < pending.context->metrics_list.size(); i++) {
|
||||
const rocmtools::Metric* metric = pending.context->metrics_list[i];
|
||||
@@ -453,41 +450,67 @@ bool AsyncSignalHandler(hsa_signal_value_t signal_value, void* data) {
|
||||
hsa_amd_profiling_dispatch_time_t time;
|
||||
hsa_support::GetAmdExtTable().hsa_amd_profiling_get_dispatch_time_fn(
|
||||
queue_info_session->agent, pending.signal, &time);
|
||||
rocprofiler_record_profiler_t record{};
|
||||
record.gpu_id = rocprofiler_agent_id_t{
|
||||
(uint64_t)hsa_support::GetAgentInfo(queue_info_session->agent.handle).getIndex()};
|
||||
record.kernel_properties = pending.kernel_properties;
|
||||
record.thread_id = rocprofiler_thread_id_t{pending.thread_id};
|
||||
record.queue_idx = rocprofiler_queue_index_t{pending.queue_index};
|
||||
record.timestamps = rocprofiler_record_header_timestamp_t{time.start, time.end};
|
||||
record.queue_id = rocprofiler_queue_id_t{queue_info_session->queue_id};
|
||||
if (pending.counters_count > 0 && pending.context->metrics_list.size() > 0 &&
|
||||
pending.profile) {
|
||||
AddRecordCounters(&record, pending);
|
||||
uint32_t record_count = 1;
|
||||
bool is_individual_xcc_mode = false;
|
||||
uint32_t xcc_count =
|
||||
hsa_support::GetAgentInfo(queue_info_session->agent.handle).getXccCount();
|
||||
if (xcc_count > 1) { // for MI300
|
||||
const char* str = getenv("ROCPROFILER_INDIVIDUAL_XCC_MODE");
|
||||
if (str != NULL) is_individual_xcc_mode = (atol(str) > 0);
|
||||
// for individual xcc mode, there will be xcc_count records for each dispatch
|
||||
// for accumulation mode, there will be only one record for a dispatch
|
||||
if (is_individual_xcc_mode) record_count = xcc_count;
|
||||
}
|
||||
// Kernel Descriptor is the right record id generated in the WriteInterceptor function and
|
||||
// will be used to handle the kernel name of that dispatch
|
||||
record.header = {ROCPROFILER_PROFILER_RECORD,
|
||||
rocprofiler_record_id_t{pending.kernel_descriptor}};
|
||||
record.kernel_id = rocprofiler_kernel_id_t{pending.kernel_descriptor};
|
||||
for (uint32_t xcc_id = 0; xcc_id < record_count; xcc_id++) {
|
||||
rocprofiler_record_profiler_t record{};
|
||||
// TODO: (sauverma) gpu-id will need to support xcc like so- 1.1, 1.2, 1.3 ... 1.5 for
|
||||
// different xcc
|
||||
record.gpu_id = rocprofiler_agent_id_t{
|
||||
(uint64_t)hsa_support::GetAgentInfo(queue_info_session->agent.handle).getIndex() +
|
||||
xcc_id};
|
||||
record.kernel_properties = pending.kernel_properties;
|
||||
record.thread_id = rocprofiler_thread_id_t{pending.thread_id};
|
||||
record.queue_idx = rocprofiler_queue_index_t{pending.queue_index};
|
||||
record.timestamps = rocprofiler_record_header_timestamp_t{time.start, time.end};
|
||||
record.queue_id = rocprofiler_queue_id_t{queue_info_session->queue_id};
|
||||
if (pending.counters_count > 0 && pending.context->metrics_list.size() > 0 &&
|
||||
pending.profile) {
|
||||
if (xcc_id == 0) // call to GetCounterData() is required only once for a dispatch
|
||||
rocmtools::metrics::GetCounterData(pending.profile, queue_info_session->agent,
|
||||
pending.context->results_list);
|
||||
if (is_individual_xcc_mode)
|
||||
rocmtools::metrics::GetCountersAndMetricResultsByXcc(
|
||||
xcc_id, pending.context->results_list, pending.context->results_map,
|
||||
pending.context->metrics_list);
|
||||
else
|
||||
rocmtools::metrics::GetMetricsData(pending.context->results_map,
|
||||
pending.context->metrics_list);
|
||||
AddRecordCounters(&record, pending);
|
||||
}
|
||||
// Kernel Descriptor is the right record id generated in the WriteInterceptor function and
|
||||
// will be used to handle the kernel name of that dispatch
|
||||
record.header = {ROCPROFILER_PROFILER_RECORD,
|
||||
rocprofiler_record_id_t{pending.kernel_descriptor}};
|
||||
record.kernel_id = rocprofiler_kernel_id_t{pending.kernel_descriptor};
|
||||
|
||||
if (pending.session_id.handle == 0) {
|
||||
pending.session_id = GetROCMToolObj()->GetCurrentSessionId();
|
||||
}
|
||||
if (session->FindBuffer(pending.buffer_id)) {
|
||||
Memory::GenericBuffer* buffer = session->GetBuffer(pending.buffer_id);
|
||||
if (pending.profile && pending.counters_count > 0) {
|
||||
rocprofiler_record_counter_instance_t* record_counters = record.counters;
|
||||
buffer->AddRecord(
|
||||
record, record.counters,
|
||||
(record.counters_count.value * (sizeof(rocprofiler_record_counter_instance_t) + 1)),
|
||||
[](auto& record, const void* data) {
|
||||
record.counters = const_cast<rocprofiler_record_counter_instance_t*>(
|
||||
static_cast<const rocprofiler_record_counter_instance_t*>(data));
|
||||
});
|
||||
free(record_counters);
|
||||
} else {
|
||||
buffer->AddRecord(record);
|
||||
if (pending.session_id.handle == 0) {
|
||||
pending.session_id = GetROCMToolObj()->GetCurrentSessionId();
|
||||
}
|
||||
if (session->FindBuffer(pending.buffer_id)) {
|
||||
Memory::GenericBuffer* buffer = session->GetBuffer(pending.buffer_id);
|
||||
if (pending.profile && pending.counters_count > 0) {
|
||||
rocprofiler_record_counter_instance_t* record_counters = record.counters;
|
||||
buffer->AddRecord(
|
||||
record, record.counters,
|
||||
(record.counters_count.value * (sizeof(rocprofiler_record_counter_instance_t) + 1)),
|
||||
[](auto& record, const void* data) {
|
||||
record.counters = const_cast<rocprofiler_record_counter_instance_t*>(
|
||||
static_cast<const rocprofiler_record_counter_instance_t*>(data));
|
||||
});
|
||||
free(record_counters);
|
||||
} else {
|
||||
buffer->AddRecord(record);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pending.counters_count > 0 && pending.profile && pending.profile->events) {
|
||||
|
||||
@@ -245,7 +245,7 @@ void DeviceProfileSession::PollMetrics(rocprofiler_device_profile_metric_t* data
|
||||
::signalWait(read_packet_.completion_signal, 1);
|
||||
|
||||
// Collect counter values for events
|
||||
metrics::GetCounterData(profile_, results_list_);
|
||||
metrics::GetCounterData(profile_, gpu_agent_, results_list_);
|
||||
|
||||
// evaluate metrics based on collected counter values
|
||||
metrics::GetMetricsData(results_map_, metrics_list_);
|
||||
|
||||
Αναφορά σε νέο ζήτημα
Block a user