[SWDEV-519061] xgmi command output shows zero for all xgmi acc read/write data in the first column (#392)

The xgmi read and write accumulated data from gpu metric index
is based on sysfs xgmi_port_num file. Mapped these two to display
read and write wrt src_gpu Vs dst_gpu.
---------

Signed-off-by: Bindhiya Kanangot Balakrishnan <Bindhiya.KanangotBalakrishnan@amd.com>
このコミットが含まれているのは:
Kanangot Balakrishnan, Bindhiya
2025-06-02 14:01:06 -05:00
committed by GitHub
コミット 8ed52616ad
7個のファイルの変更161行の追加57行の削除
+34 -47
ファイルの表示
@@ -5948,7 +5948,6 @@ class AMDSMICommands():
xgmi_dict['link_metrics']['max_bandwidth'] = max_bandwidth
# Populate link metrics
link_num = 0
for dest_gpu in args.gpu:
partition_id = -1
try:
@@ -5965,57 +5964,45 @@ class AMDSMICommands():
dest_link_dict = {
"gpu" : dest_gpu_id,
"bdf" : dest_gpu_bdf,
"read" : "N/A",
"write" : "N/A"
"read" : 0,
"write" : 0,
}
# Don't make a call to check link status for the same gpu
if dest_gpu_bdf == src_gpu_bdf:
found = False
for link in xgmi_metrics_info['links']:
if link['bdf'] == dest_gpu_bdf:
# Accumulate read/write if multiple links have the same bdf
dest_link_dict['read'] += link['read']
dest_link_dict['write'] += link['write']
found = True
if not found:
dest_link_dict['read'] = "N/A"
dest_link_dict['write'] = "N/A"
xgmi_dict['link_metrics']['links'].append(dest_link_dict)
continue
else:
data_unit = 'KB'
if self.logger.is_human_readable_format():
dest_link_dict['read'] = self.helpers.convert_bytes_to_readable(dest_link_dict['read'] * 1024, True)
dest_link_dict['write'] = self.helpers.convert_bytes_to_readable(dest_link_dict['write'] * 1024, True)
elif self.logger.is_json_format():
dest_link_dict['read'] = {"value" : dest_link_dict['read'],
"unit" : data_unit}
dest_link_dict['write'] = {"value" : dest_link_dict['write'],
"unit" : data_unit}
try:
# Get the read write relative to the source gpu
read = xgmi_metrics_info['links'][link_num]['read']
write = xgmi_metrics_info['links'][link_num]['write']
link_num += 1
except (KeyError, amdsmi_exception.AmdSmiLibraryException) as e:
read = "N/A"
write = "N/A"
logging.debug("Failed to get read data for %s to %s | %s",
self.helpers.get_gpu_id_from_device_handle(src_gpu),
self.helpers.get_gpu_id_from_device_handle(dest_gpu),
e.get_error_info())
data_unit = 'KB'
if self.logger.is_human_readable_format():
dest_link_dict['read'] = self.helpers.convert_bytes_to_readable(read * 1024, True)
dest_link_dict['write'] = self.helpers.convert_bytes_to_readable(write * 1024, True)
elif self.logger.is_json_format():
dest_link_dict['read'] = {"value" : read,
"unit" : data_unit}
dest_link_dict['write'] = {"value" : write,
"unit" : data_unit}
elif self.logger.is_csv_format():
dest_link_dict['read'] = read
dest_link_dict['write'] = write
try:
link_type = amdsmi_interface.amdsmi_topo_get_link_type(src_gpu, dest_gpu)['type']
if xgmi_dict['link_metrics']['link_type'] != "XGMI" and isinstance(link_type, int):
if link_type == amdsmi_interface.amdsmi_wrapper.AMDSMI_LINK_TYPE_INTERNAL:
xgmi_dict['link_metrics']['link_type'] = "UNKNOWN"
elif link_type == amdsmi_interface.amdsmi_wrapper.AMDSMI_LINK_TYPE_PCIE:
xgmi_dict['link_metrics']['link_type'] = "PCIE"
elif link_type == amdsmi_interface.amdsmi_wrapper.AMDSMI_LINK_TYPE_XGMI:
xgmi_dict['link_metrics']['link_type'] = "XGMI"
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug("Failed to get link type for %s to %s | %s",
self.helpers.get_gpu_id_from_device_handle(src_gpu),
self.helpers.get_gpu_id_from_device_handle(dest_gpu),
e.get_error_info())
try:
link_type = amdsmi_interface.amdsmi_topo_get_link_type(src_gpu, dest_gpu)['type']
if xgmi_dict['link_metrics']['link_type'] != "XGMI" and isinstance(link_type, int):
if link_type == amdsmi_interface.amdsmi_wrapper.AMDSMI_LINK_TYPE_INTERNAL:
xgmi_dict['link_metrics']['link_type'] = "UNKNOWN"
elif link_type == amdsmi_interface.amdsmi_wrapper.AMDSMI_LINK_TYPE_PCIE:
xgmi_dict['link_metrics']['link_type'] = "PCIE"
elif link_type == amdsmi_interface.amdsmi_wrapper.AMDSMI_LINK_TYPE_XGMI:
xgmi_dict['link_metrics']['link_type'] = "XGMI"
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug("Failed to get link type for %s to %s | %s",
self.helpers.get_gpu_id_from_device_handle(src_gpu),
self.helpers.get_gpu_id_from_device_handle(dest_gpu),
e.get_error_info())
xgmi_dict['link_metrics']['links'].append(dest_link_dict)
+2 -6
ファイルの表示
@@ -3112,22 +3112,18 @@ def amdsmi_get_link_metrics(processor_handle: amdsmi_wrapper.amdsmi_processor_ha
)
)
bdf = amdsmi_wrapper.amdsmi_bdf_t()
# TODO: Dummy BDF - to be replaced with destination BDF from xgmi_port_num when available
bdf.struct_amdsmi_bdf_t = amdsmi_wrapper.struct_amdsmi_bdf_t(0xFFFF, 0xFF, 0xFF, 0xF)
links = []
for i in range(AMDSMI_MAX_NUM_XGMI_LINKS):
link = link_metrics.links[i]
links.append({
"bdf": _format_bdf(bdf),
"bdf": _format_bdf(link.bdf),
"link_type": link.link_type,
"read": link.read,
"write": link.write,
})
return {
"num_links": AMDSMI_MAX_NUM_XGMI_LINKS,
"num_links": link_metrics.num_links,
"bit_rate": link_metrics.bit_rate,
"max_bandwidth": link_metrics.max_bandwidth,
"links": links
+20
ファイルの表示
@@ -1994,6 +1994,26 @@ rsmi_status_t rsmi_dev_unique_id_get(uint32_t dv_ind, uint64_t *id);
*/
rsmi_status_t rsmi_dev_xgmi_physical_id_get(uint32_t dv_ind, uint16_t *id);
/**
* @brief Get the XGMI src_gpu to dest_gpu link_num based mapping for the device
*
* @details Given a device index @p dv_ind, a pointer to a uint16_t to get the
* count of XGMI links, and a pointer to a uint16_t array to which the dest_gpu's
* order will be written
*
* @param[in] dv_ind a device index
*
* @param[inout] count a pointer to uint16_t to which the count of XGMI links
* will be written
*
* @param[inout] xgmi_dst_gpu_order a pointer to uint16_t array to which the
* dest_gpu's order will be written
*
* @retval ::RSMI_STATUS_SUCCESS is returned upon successful call.
*
*/
rsmi_status_t rsmi_dev_xgmi_port_num_get(uint32_t dv_ind, uint32_t *count, uint16_t *link_to_dst_gpu);
/**
* @brief Get the GUID, also known as the GPU device id,
* associated with the provided device index indicated by KFD.
+1
ファイルの表示
@@ -89,6 +89,7 @@ enum DevInfoTypes {
kDevMemOverDriveLevel,
kDevDevID,
kDevXGMIPhysicalID,
kDevXGMIPortNum,
kDevDevRevID,
kDevDevProdName,
kDevDevProdNum,
+56
ファイルの表示
@@ -274,6 +274,25 @@ static rsmi_status_t get_dev_value_str(amd::smi::DevInfoTypes type,
return amd::smi::ErrnoToRsmiStatus(ret);
}
static rsmi_status_t read_dev_port_map_file(amd::smi::DevInfoTypes type, uint32_t dv_ind, std::string *val_str) {
assert(val_str != nullptr);
if (val_str == nullptr) {
return RSMI_STATUS_INVALID_ARGS;
}
GET_DEV_FROM_INDX
std::string file_path = dev->get_sys_file_path_by_type(type);
if (file_path.empty()) {
return RSMI_STATUS_FILE_ERROR;
}
std::ifstream infile(file_path);
if (!infile) {
return RSMI_STATUS_FILE_ERROR;
}
std::ostringstream ss;
ss << infile.rdbuf();
*val_str = ss.str();
return RSMI_STATUS_SUCCESS;
}
static rsmi_status_t get_dev_value_int(amd::smi::DevInfoTypes type,
uint32_t dv_ind, uint64_t *val_int) {
assert(val_int != nullptr);
@@ -974,6 +993,43 @@ rsmi_dev_xgmi_physical_id_get(uint32_t dv_ind, uint16_t *id) {
return ret;
}
rsmi_status_t
rsmi_dev_xgmi_port_num_get(uint32_t dv_ind, uint32_t *count, uint16_t *link_to_dst_node) {
std::ostringstream ss;
rsmi_status_t ret;
ss << __PRETTY_FUNCTION__ << "| ======= start =======";
LOG_TRACE(ss);
CHK_SUPPORT_NAME_ONLY(link_to_dst_node)
*link_to_dst_node = std::numeric_limits<uint16_t>::max();
std::string s;
ret = read_dev_port_map_file(amd::smi::kDevXGMIPortNum, dv_ind, &s);
std::istringstream iss(s);
std::string line;
*count = 0;
while (std::getline(iss, line)) {
if (line.empty()) continue;
std::istringstream f(line);
std::string src_token, arrow, dst_token;
if (f >> src_token >> arrow >> dst_token) {
size_t src_colon = src_token.find(':');
size_t dst_colon = dst_token.find(':');
if (src_colon != std::string::npos && dst_colon != std::string::npos) {
uint16_t src_link = static_cast<uint16_t>(std::stoi(src_token.substr(src_colon + 1)));
uint16_t dst_node = static_cast<uint16_t>(std::stoi(dst_token.substr(0, dst_colon)));
link_to_dst_node[src_link] = dst_node;
(*count)++;
}
}
}
ss << __PRETTY_FUNCTION__ << " | ======= end ======="
<< ", reporting " << amd::smi::getRSMIStatusString(ret);
LOG_TRACE(ss);
return ret;
}
rsmi_status_t
rsmi_dev_revision_get(uint32_t dv_ind, uint16_t *revision) {
std::ostringstream outss;
+6
ファイルの表示
@@ -69,6 +69,7 @@ static const char *kDevDevProdNameFName = "product_name";
static const char *kDevDevProdNumFName = "product_number";
static const char *kDevDevIDFName = "device";
static const char* kDevXGMIPhysicalIDFName = "xgmi_physical_id";
static const char *kDevXGMIPortNumFName = "xgmi_port_num";
static const char *kDevDevRevIDFName = "revision";
static const char *kDevVendorIDFName = "vendor";
static const char *kDevBoardInfoFName = "board_info";
@@ -249,6 +250,7 @@ static const std::map<DevInfoTypes, const char *> kDevAttribNameMap = {
{kDevDevProdNum, kDevDevProdNumFName},
{kDevDevID, kDevDevIDFName},
{kDevXGMIPhysicalID, kDevXGMIPhysicalIDFName},
{kDevXGMIPortNum, kDevXGMIPortNumFName},
{kDevDevRevID, kDevDevRevIDFName},
{kDevVendorID, kDevVendorIDFName},
{kDevPCieVendorID, kDevPCieVendorIDFName},
@@ -420,6 +422,7 @@ Device::devInfoTypesStrings = {
{kDevMemOverDriveLevel, "kDevMemOverDriveLevel"},
{kDevDevID, "kDevDevID"},
{kDevXGMIPhysicalID, "kDevXGMIPhysicalID"},
{kDevXGMIPortNum, "kDevXGMIPortNum"},
{kDevDevRevID, "kDevDevRevID"},
{kDevDevProdName, "kDevDevProdName"},
{kDevBoardInfo, "kDevBoardInfo"},
@@ -521,6 +524,7 @@ static const std::map<const char *, dev_depends_t> kDevFuncDependsMap = {
{"rsmi_dev_vram_vendor_get", {{kDevVramVendorFName}, {}}},
{"rsmi_dev_id_get", {{kDevDevIDFName}, {}}},
{"rsmi_dev_xgmi_physical_id_get", {{kDevXGMIPhysicalIDFName}, {}}},
{"rsmi_dev_xgmi_port_num_get", {{kDevXGMIPortNumFName}, {}}},
{"rsmi_dev_revision_get", {{kDevDevRevIDFName}, {}}},
{"rsmi_dev_vendor_id_get", {{kDevVendorIDFName}, {}}},
{"rsmi_dev_name_get", {{kDevVendorIDFName,
@@ -1198,6 +1202,7 @@ int Device::readDevInfo(DevInfoTypes type, uint64_t *val) {
case kDevPCieVendorID:
case kDevErrCntFeatures:
case kDevXGMIPhysicalID:
case kDevXGMIPortNum:
case kDevErrRASSchema:
case kDevErrTableVersion:
ret = readDevInfoStr(type, &tempStr);
@@ -1380,6 +1385,7 @@ int Device::readDevInfo(DevInfoTypes type, std::string *val) {
case kDevMemoryPartition:
case kDevNumaNode:
case kDevXGMIPhysicalID:
case kDevXGMIPortNum:
case kDevAvailableMemoryPartition:
case kDevProcessIsolation:
case kDevSupportedXcpConfigs:
+42 -4
ファイルの表示
@@ -1747,9 +1747,6 @@ amdsmi_get_gpu_xgmi_link_status(amdsmi_processor_handle processor_handle,
uint32_t dev_num = 0;
rsmi_num_monitor_devices(&dev_num);
link_status->total_links = AMDSMI_MAX_NUM_XGMI_LINKS;
if (dev_num <= link_status->total_links) {
link_status->total_links = dev_num;
}
// get the status values from the metric info
for (unsigned int i = 0; i < link_status->total_links; i++) {
if (metric_info.xgmi_link_status[i] == std::numeric_limits<uint16_t>::max()) {
@@ -2132,12 +2129,53 @@ amdsmi_status_t amdsmi_get_link_metrics(amdsmi_processor_handle processor_handle
(metric_info.xgmi_link_width != std::numeric_limits<uint16_t>::max()))
link_metrics->max_bandwidth = metric_info.xgmi_link_speed * metric_info.xgmi_link_width;
uint16_t link_to_dst_node[AMDSMI_MAX_NUM_XGMI_LINKS];
std::fill_n(link_to_dst_node, AMDSMI_MAX_NUM_XGMI_LINKS, std::numeric_limits<uint16_t>::max());
status = rsmi_wrapper(rsmi_dev_xgmi_port_num_get, processor_handle, 0,
&link_metrics->num_links, link_to_dst_node);
for (unsigned int i = 0; i < AMDSMI_MAX_NUM_XGMI_LINKS; i++) {
memset(&link_metrics->links[i].bdf, 0xFF, sizeof(amdsmi_bdf_t));
if (link_to_dst_node[i] != std::numeric_limits<uint16_t>::max()) {
uint32_t node_id = link_to_dst_node[i];
std::string node_symlink = "node" + std::to_string(node_id);
std::string sysfs_base = "/sys/bus/pci/devices/";
DIR *dir = opendir(sysfs_base.c_str());
if (dir) {
struct dirent *entry;
while ((entry = readdir(dir)) != nullptr) {
if (entry->d_type != DT_DIR && entry->d_type != DT_LNK)
continue;
std::string bdf = entry->d_name;
if (bdf == "." || bdf == "..") continue;
std::string symlink_path = sysfs_base + bdf + "/xgmi_hive_info/" + node_symlink;
char buf[PATH_MAX] = {0};
ssize_t len = readlink(symlink_path.c_str(), buf, sizeof(buf)-1);
if (len > 0) {
buf[len] = '\0';
std::string target(buf);
size_t last_slash = target.find_last_of('/');
std::string bdf_str = (last_slash != std::string::npos) ? target.substr(last_slash + 1) : target;
// Parse BDF string: "dddd:bb:dd.f"
unsigned domain = 0, bus = 0, device = 0, function = 0;
if (sscanf(bdf_str.c_str(), "%4x:%2x:%2x.%1x", &domain, &bus, &device, &function) == 4) {
amdsmi_bdf_t dst_bdf = {};
dst_bdf.domain_number = static_cast<uint16_t>(domain);
dst_bdf.bus_number = static_cast<uint8_t>(bus);
dst_bdf.device_number = static_cast<uint8_t>(device);
dst_bdf.function_number = static_cast<uint8_t>(function);
link_metrics->links[i].bdf = dst_bdf;
}
break; // Found, stop searching
}
}
closedir(dir);
}
}
link_metrics->links[i].read = metric_info.xgmi_read_data_acc[i];
link_metrics->links[i].write = metric_info.xgmi_write_data_acc[i];
link_metrics->links[i].link_type = AMDSMI_LINK_TYPE_XGMI;
}
return AMDSMI_STATUS_SUCCESS;
}