diff --git a/projects/rocprofiler/src/core/counters/metrics/eval_metrics.cpp b/projects/rocprofiler/src/core/counters/metrics/eval_metrics.cpp index bbe39d61c6..e6c91608c6 100644 --- a/projects/rocprofiler/src/core/counters/metrics/eval_metrics.cpp +++ b/projects/rocprofiler/src/core/counters/metrics/eval_metrics.cpp @@ -2,6 +2,7 @@ #include "src/utils/helper.h" #include "src/core/hsa/hsa_common.h" #include +#include using namespace rocmtools; @@ -25,6 +26,7 @@ struct block_status_t { typedef struct { std::vector* 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 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_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& results_map, return true; } + +void metrics::GetCountersAndMetricResultsByXcc(uint32_t xcc_index, std::vector& results_list, + std::map& results_map, + std::vector& 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); +} diff --git a/projects/rocprofiler/src/core/counters/metrics/eval_metrics.h b/projects/rocprofiler/src/core/counters/metrics/eval_metrics.h index 1b5cbec37a..67855c064a 100644 --- a/projects/rocprofiler/src/core/counters/metrics/eval_metrics.h +++ b/projects/rocprofiler/src/core/counters/metrics/eval_metrics.h @@ -33,11 +33,20 @@ THE SOFTWARE. namespace rocmtools { -typedef struct { +typedef std::vector 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>& 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_list); bool GetMetricsData(std::map& results_map, std::vector& metrics_list); +void GetCountersAndMetricResultsByXcc(uint32_t xcc_index, std::vector& results_list, + std::map& results_map, + std::vector& metrics_list); + } // namespace metrics } // namespace rocmtools diff --git a/projects/rocprofiler/src/core/hardware/hsa_info.cpp b/projects/rocprofiler/src/core/hardware/hsa_info.cpp index 80c4cc6983..7c3ea2ca66 100644 --- a/projects/rocprofiler/src/core/hardware/hsa_info.cpp +++ b/projects/rocprofiler/src/core/hardware/hsa_info.cpp @@ -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; } diff --git a/projects/rocprofiler/src/core/hardware/hsa_info.h b/projects/rocprofiler/src/core/hardware/hsa_info.h index eee93df3a6..2586065f19 100644 --- a/projects/rocprofiler/src/core/hardware/hsa_info.h +++ b/projects/rocprofiler/src/core/hardware/hsa_info.h @@ -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_; diff --git a/projects/rocprofiler/src/core/hsa/queues/queue.cpp b/projects/rocprofiler/src/core/hsa/queues/queue.cpp index 88d1f96393..6195387216 100644 --- a/projects/rocprofiler/src/core/hsa/queues/queue.cpp +++ b/projects/rocprofiler/src/core/hsa/queues/queue.cpp @@ -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 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( - static_cast(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( + static_cast(data)); + }); + free(record_counters); + } else { + buffer->AddRecord(record); + } } } if (pending.counters_count > 0 && pending.profile && pending.profile->events) { diff --git a/projects/rocprofiler/src/core/session/device_profiling.cpp b/projects/rocprofiler/src/core/session/device_profiling.cpp index e847c89755..f9b1e269d4 100644 --- a/projects/rocprofiler/src/core/session/device_profiling.cpp +++ b/projects/rocprofiler/src/core/session/device_profiling.cpp @@ -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_);