[SWDEV-488303] Updated CU occupancy for per-process retrieval (#243)

Change-Id: I2990597c6dd4b2e8cf3e11ce60f72049ebdd9a8c
Signed-off-by: Maisam Arif <Maisam.Arif@amd.com>
This commit is contained in:
Arif, Maisam
2025-05-29 20:35:27 -05:00
committed by GitHub
parent fba62e2270
commit 0fdaebdbaa
12 changed files with 232 additions and 259 deletions
+6
View File
@@ -216,6 +216,9 @@ int32_t AMDSmiGPUDevice::get_compute_process_list_impl(GPUComputeProcessList_t&
/**
* Complete the process information
* This is where we copy rsmi_process_info_t into the larger amdsmi_proc_info_t
* Then populate the remaining fields with the gpuvsmi_get_pid_info()
* TODO FIX HERE TO GRAB KFD VRAM if /proc is inconsistent
*/
auto get_process_info = [&](const rsmi_process_info_t& rsmi_proc_info, amdsmi_proc_info_t& asmi_proc_info) {
auto status_code = gpuvsmi_get_pid_info(get_bdf(), rsmi_proc_info.process_id, asmi_proc_info);
@@ -225,6 +228,9 @@ int32_t AMDSmiGPUDevice::get_compute_process_list_impl(GPUComputeProcessList_t&
asmi_proc_info.memory_usage.vram_mem = rsmi_proc_info.vram_usage;
}
// Copy the cu occupancy from rsmi_process_info_t to amdsmi_proc_info_t
asmi_proc_info.cu_occupancy = rsmi_proc_info.cu_occupancy;
return status_code;
};
+157 -190
View File
@@ -20,16 +20,17 @@
* THE SOFTWARE.
*/
#include <sys/types.h>
#include <dirent.h>
#include <inttypes.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <memory>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <fstream>
#include <algorithm>
#include <string.h>
#include <memory>
#include <vector>
#include "amd_smi/amdsmi.h"
#include "amd_smi/impl/amd_smi_utils.h"
@@ -37,230 +38,196 @@
extern "C" {
static const char *container_type_name[AMDSMI_MAX_CONTAINER_TYPE] = {
[AMDSMI_CONTAINER_LXC] = "lxc",
[AMDSMI_CONTAINER_DOCKER] = "docker",
[AMDSMI_CONTAINER_LXC] = "lxc",
[AMDSMI_CONTAINER_DOCKER] = "docker",
};
amdsmi_status_t gpuvsmi_pid_is_gpu(const std::string &path, const char *bdf)
{
DIR *d;
struct dirent *dir;
amdsmi_status_t gpuvsmi_pid_is_gpu(const std::string &path, const char *bdf) {
DIR *d;
struct dirent *dir;
d = opendir(path.c_str());
if (!d)
return AMDSMI_STATUS_NO_PERM;
d = opendir(path.c_str());
if (!d) return AMDSMI_STATUS_NO_PERM;
/* iterate through all the fds, try to find
* a match for the GPU bdf
*/
while ((dir = readdir(d)) != NULL) {
std::string file = path + dir->d_name;
std::ifstream fdinfo(file.c_str());
for (std::string line; std::getline(fdinfo, line);) {
if (line.find(bdf) != std::string::npos) {
closedir(d);
return AMDSMI_STATUS_SUCCESS;
}
}
}
/* iterate through all the fds, try to find
* a match for the GPU bdf
*/
while ((dir = readdir(d)) != NULL) {
std::string file = path + dir->d_name;
std::ifstream fdinfo(file.c_str());
for (std::string line; std::getline(fdinfo, line);) {
if (line.find(bdf) != std::string::npos) {
closedir(d);
return AMDSMI_STATUS_SUCCESS;
}
}
}
closedir(d);
closedir(d);
return AMDSMI_STATUS_NOT_FOUND;
return AMDSMI_STATUS_NOT_FOUND;
}
amdsmi_status_t gpuvsmi_get_pids(const amdsmi_bdf_t &bdf, std::vector<long int> &pids, uint64_t *size)
{
char bdf_str[13];
DIR *d;
struct dirent *dir;
amdsmi_status_t gpuvsmi_get_pids(const amdsmi_bdf_t &bdf, std::vector<long int> &pids,
uint64_t *size) {
char bdf_str[13];
DIR *d;
struct dirent *dir;
/* 0000:00:00.0 */
snprintf(bdf_str, 13, "%04" PRIx32 ":%02" PRIx32 ":%02" PRIx32 ".%" PRIu32,
static_cast<uint32_t>(bdf.domain_number & 0xffff),
static_cast<uint32_t>(bdf.bus_number & 0xff),
static_cast<uint32_t>(bdf.device_number & 0x1f),
static_cast<uint32_t>(bdf.function_number & 0x7));
/* 0000:00:00.0 */
snprintf(bdf_str, 13, "%04" PRIx32 ":%02" PRIx32 ":%02" PRIx32 ".%" PRIu32,
static_cast<uint32_t>(bdf.domain_number & 0xffff),
static_cast<uint32_t>(bdf.bus_number & 0xff),
static_cast<uint32_t>(bdf.device_number & 0x1f),
static_cast<uint32_t>(bdf.function_number & 0x7));
d = opendir("/proc");
if (!d)
return AMDSMI_STATUS_NO_PERM;
d = opendir("/proc");
if (!d) return AMDSMI_STATUS_NO_PERM;
pids.clear();
/* Find the pid folders in /proc/ that we have access to */
while ((dir = readdir(d)) != NULL) {
if (dir->d_type == DT_DIR) {
/* Try to cast the name of the folder to a
* number, if it fails, it is not */
char *p;
long int pid;
pids.clear();
/* Find the pid folders in /proc/ that we have access to */
while ((dir = readdir(d)) != NULL) {
if (dir->d_type == DT_DIR) {
/* Try to cast the name of the folder to a
* number, if it fails, it is not */
char *p;
long int pid;
pid = strtol(dir->d_name, &p, 10);
if (*p != 0)
continue;
pid = strtol(dir->d_name, &p, 10);
if (*p != 0) continue;
/* Check if fdinfo is accesible */
std::string path = "/proc/" + std::string(dir->d_name) + "/fdinfo/";
/* Check if fdinfo is accesible */
std::string path = "/proc/" + std::string(dir->d_name) + "/fdinfo/";
if (access(path.c_str(), R_OK))
continue;
if (access(path.c_str(), R_OK)) continue;
/* check if GPU is present */
if (gpuvsmi_pid_is_gpu(path, bdf_str))
continue;
pids.push_back(pid);
}
}
closedir(d);
/* check if GPU is present */
if (gpuvsmi_pid_is_gpu(path, bdf_str)) continue;
pids.push_back(pid);
}
}
closedir(d);
*size = pids.size();
return AMDSMI_STATUS_SUCCESS;
*size = pids.size();
return AMDSMI_STATUS_SUCCESS;
}
amdsmi_status_t gpuvsmi_get_pid_info(const amdsmi_bdf_t &bdf, long int pid,
amdsmi_proc_info_t &info)
{
char bdf_str[13];
DIR *d;
struct dirent *dir;
amdsmi_proc_info_t &info) {
char bdf_str[13];
DIR *d;
struct dirent *dir;
/* 0000:00:00.0 */
snprintf(bdf_str, 13, "%04" PRIx32 ":%02" PRIx32 ":%02" PRIx32 ".%" PRIu32,
static_cast<uint32_t>(bdf.domain_number & 0xffff),
static_cast<uint32_t>(bdf.bus_number & 0xff),
static_cast<uint32_t>(bdf.device_number & 0x1f),
static_cast<uint32_t>(bdf.function_number & 0x7));
/* 0000:00:00.0 */
snprintf(bdf_str, 13, "%04" PRIx32 ":%02" PRIx32 ":%02" PRIx32 ".%" PRIu32,
static_cast<uint32_t>(bdf.domain_number & 0xffff),
static_cast<uint32_t>(bdf.bus_number & 0xff),
static_cast<uint32_t>(bdf.device_number & 0x1f),
static_cast<uint32_t>(bdf.function_number & 0x7));
std::string path = "/proc/" + std::to_string(pid) + "/fdinfo/";
std::string name_path = "/proc/" + std::to_string(pid) + "/comm";
std::string cgroup_path = "/proc/" + std::to_string(pid) + "/cgroup";
std::string path = "/proc/" + std::to_string(pid) + "/fdinfo/";
std::string name_path = "/proc/" + std::to_string(pid) + "/comm";
std::string cgroup_path = "/proc/" + std::to_string(pid) + "/cgroup";
if (gpuvsmi_pid_is_gpu(path.c_str(), bdf_str)) {
return AMDSMI_STATUS_INVAL;
}
if (gpuvsmi_pid_is_gpu(path.c_str(), bdf_str)) {
return AMDSMI_STATUS_INVAL;
}
d = opendir(path.c_str());
if (!d)
return AMDSMI_STATUS_NO_PERM;
d = opendir(path.c_str());
if (!d) return AMDSMI_STATUS_NO_PERM;
/* Vectors to check if repated fd pasid */
// TODO remove pasid Not working in ROCm 6.4+, deprecating in 7.0
std::vector<int> pasids;
/* Vectors to check if repated fd pasid */
// TODO remove pasid Not working in ROCm 6.4+, deprecating in 7.0
std::vector<int> pasids;
memset(&info, 0, sizeof(info));
/* Iterate through all fdinfos */
while ((dir = readdir(d)) != NULL) {
memset(&info, 0, sizeof(info));
/* Iterate through all fdinfos */
while ((dir = readdir(d)) != NULL) {
std::string file = path + dir->d_name;
std::ifstream fdinfo(file.c_str());
std::string file = path + dir->d_name;
std::ifstream fdinfo(file.c_str());
for (std::string bdfline; getline(fdinfo, bdfline);) {
if (bdfline.find("drm-pdev:") != std::string::npos) {
char fd_bdf_str[13];
for (std::string bdfline; getline(fdinfo, bdfline);) {
if (bdfline.find("drm-pdev:") != std::string::npos) {
char fd_bdf_str[13];
/* Only check against fdinfo files that contain a bdf */
if (sscanf(bdfline.c_str(), "drm-pdev: %s", &fd_bdf_str[0]) != 1) continue;
/* Only check against fdinfo files that contain a bdf */
if (sscanf(bdfline.c_str(), "drm-pdev: %s", &fd_bdf_str[0]) != 1)
continue;
/* Populate amdsmi_proc_info_t struct only if the bdf in
* the fdinfo file matches the passed bdf */
if (strncmp(bdf_str, fd_bdf_str, 13) == 0) {
std::ifstream fdinfo(file.c_str());
/* Populate amdsmi_proc_info_t struct only if the bdf in
* the fdinfo file matches the passed bdf */
if (strncmp(bdf_str, fd_bdf_str, 13) == 0){
std::ifstream fdinfo(file.c_str());
for (std::string line; getline(fdinfo, line);) {
if (line.find("pasid:") != std::string::npos) {
int pasid;
if (sscanf(line.c_str(), "pasid: %d", &pasid) != 1) continue;
auto it = std::find(pasids.begin(), pasids.end(), pasid);
if (it == pasids.end()) pasids.push_back(pasid);
} else if (line.find("drm-memory-gtt:") != std::string::npos) {
unsigned long mem;
if (sscanf(line.c_str(), "drm-memory-gtt: %lu", &mem) != 1) continue;
info.mem += mem * 1000;
info.memory_usage.gtt_mem += mem * 1000;
} else if (line.find("drm-memory-cpu:") != std::string::npos) {
unsigned long mem;
if (sscanf(line.c_str(), "drm-memory-cpu: %lu", &mem) != 1) continue;
info.mem += mem * 1000;
info.memory_usage.cpu_mem += mem * 1000;
} else if (line.find("drm-memory-vram:") != std::string::npos) {
unsigned long mem;
if (sscanf(line.c_str(), "drm-memory-vram: %lu", &mem) != 1) continue;\
info.mem += mem * 1000;
info.memory_usage.vram_mem += mem * 1000;
} else if (line.find("drm-engine-gfx") != std::string::npos) {
uint64_t engine_gfx;
if (sscanf(line.c_str(), "drm-engine-gfx: %lu", &engine_gfx) != 1) continue;
info.engine_usage.gfx = engine_gfx;
} else if (line.find("drm-engine-enc") != std::string::npos) {
uint64_t engine_enc;
if (sscanf(line.c_str(), "drm-engine-enc: %lu", &engine_enc) != 1) continue;
info.engine_usage.enc = engine_enc;
}
}
}
}
}
}
for (std::string line; getline(fdinfo, line);) {
if (line.find("pasid:") != std::string::npos) {
int pasid;
if (sscanf(line.c_str(), "pasid: %d", &pasid) != 1)
continue;
auto it = std::find(pasids.begin(), pasids.end(), pasid);
if (it == pasids.end())
pasids.push_back(pasid);
} else if (line.find("drm-memory-gtt:") != std::string::npos) {
unsigned long mem;
if (sscanf(line.c_str(), "drm-memory-gtt: %lu", &mem) != 1)
continue;
info.mem += mem * 1024;
info.memory_usage.gtt_mem += mem * 1024;
} else if (line.find("drm-memory-cpu:") != std::string::npos) {
unsigned long mem;
if (sscanf(line.c_str(), "drm-memory-cpu: %lu", &mem) != 1)
continue;
info.mem += mem * 1024;
info.memory_usage.cpu_mem += mem * 1024;
} else if (line.find("drm-memory-vram:") != std::string::npos) {
unsigned long mem;
if (sscanf(line.c_str(), "drm-memory-vram: %lu", &mem) != 1)
continue;
info.mem += mem * 1024;
info.memory_usage.vram_mem += mem * 1024;
} else if (line.find("drm-engine-gfx") != std::string::npos) {
uint64_t engine_gfx;
if (sscanf(line.c_str(), "drm-engine-gfx: %lu", &engine_gfx) != 1)
continue;
info.engine_usage.gfx = engine_gfx;
} else if (line.find("drm-engine-enc") != std::string::npos) {
uint64_t engine_enc;
if (sscanf(line.c_str(), "drm-engine-enc: %lu", &engine_enc) != 1)
continue;
info.engine_usage.enc = engine_enc;
}
}
}
}
}
}
closedir(d);
closedir(d);
// Note: If possible at all, try to get the name of the process/container.
// In case the other info fail, get at least something.
std::ifstream filename(name_path.c_str());
std::string name;
std::ifstream filename(name_path.c_str());
std::string name;
getline(filename, name);
getline(filename, name);
if (name.empty())
return AMDSMI_STATUS_API_FAILED;
if (name.empty()) return AMDSMI_STATUS_API_FAILED;
strncpy(info.name, name.c_str(), std::min(
(unsigned long) AMDSMI_MAX_STRING_LENGTH,
name.length()));
strncpy(info.name, name.c_str(),
std::min((unsigned long)AMDSMI_MAX_STRING_LENGTH, name.length()));
for (int i = 0; i < AMDSMI_MAX_CONTAINER_TYPE; i++) {
std::ifstream cgroup_info(cgroup_path.c_str());
std::string container_id;
for (std::string line; getline(cgroup_info, line);) {
if (line.find(container_type_name[i]) != std::string::npos) {
container_id = line.substr(line.find(container_type_name[i]) +
strlen(container_type_name[i]) + 1, 16);
strcpy(info.container_name, container_id.c_str());
break;
}
}
if (strlen(info.container_name) > 0)
break;
}
info.pid = (uint32_t)pid;
for (int i = 0; i < AMDSMI_MAX_CONTAINER_TYPE; i++) {
std::ifstream cgroup_info(cgroup_path.c_str());
std::string container_id;
for (std::string line; getline(cgroup_info, line);) {
if (line.find(container_type_name[i]) != std::string::npos) {
container_id = line.substr(line.find(container_type_name[i]) +
strlen(container_type_name[i]) + 1, 16);
strcpy(info.container_name, container_id.c_str());
break;
}
}
if (strlen(info.container_name) > 0) break;
}
info.pid = (uint32_t)pid;
if (!pasids.size()) {
return AMDSMI_STATUS_NOT_FOUND;
if (!pasids.size()) {
return AMDSMI_STATUS_NOT_FOUND;
}
return AMDSMI_STATUS_SUCCESS;
return AMDSMI_STATUS_SUCCESS;
}
} // extern "C"
} // extern "C"