fix: [SWDEV-442525] [rocm/amd_smi_lib]
Fixes gpu_process_list
Code changes related to the following:
* amdsmi_get_gpu_process_list()
* CLI
* Examples
* Unit tests
* Changelog
* Readme
* rocm_smi_lib commit: 677433b367
Change-Id: I9210fbca7a5da92d0a8b472b72ca82597c8e4fb5
Signed-off-by: Oliveira, Daniel <daniel.oliveira@amd.com>
This commit is contained in:
+39
-60
@@ -1785,76 +1785,55 @@ amdsmi_get_gpu_total_ecc_count(amdsmi_processor_handle processor_handle, amdsmi_
|
||||
}
|
||||
|
||||
amdsmi_status_t
|
||||
amdsmi_get_gpu_process_list(amdsmi_processor_handle processor_handle, uint32_t *max_processes, amdsmi_process_handle_t *list) {
|
||||
amdsmi_get_gpu_process_list(amdsmi_processor_handle processor_handle, uint32_t *max_processes, amdsmi_proc_info_t *list) {
|
||||
AMDSMI_CHECK_INIT();
|
||||
|
||||
if (max_processes == nullptr) {
|
||||
if (!max_processes) {
|
||||
return AMDSMI_STATUS_INVAL;
|
||||
}
|
||||
|
||||
std::vector<long int> pids;
|
||||
uint32_t i = 0;
|
||||
uint64_t size = 0;
|
||||
amdsmi_status_t status;
|
||||
amd::smi::AMDSmiGPUDevice* gpu_device = nullptr;
|
||||
amdsmi_status_t r = get_gpu_device_from_handle(processor_handle, &gpu_device);
|
||||
if (r != AMDSMI_STATUS_SUCCESS)
|
||||
return r;
|
||||
amdsmi_status_t status_code = get_gpu_device_from_handle(processor_handle, &gpu_device);
|
||||
if (status_code != amdsmi_status_t::AMDSMI_STATUS_SUCCESS) {
|
||||
return status_code;
|
||||
}
|
||||
|
||||
if (gpu_device->check_if_drm_is_supported()){
|
||||
amdsmi_bdf_t bdf = gpu_device->get_bdf();
|
||||
status = gpuvsmi_get_pids(bdf, pids, &size);
|
||||
if (status != AMDSMI_STATUS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
if (*max_processes == 0 || (pids.size() == 0)) {
|
||||
*max_processes = (uint32_t)pids.size();
|
||||
return AMDSMI_STATUS_SUCCESS;
|
||||
}
|
||||
if (!list) {
|
||||
return AMDSMI_STATUS_INVAL;
|
||||
}
|
||||
if (*max_processes < pids.size()) {
|
||||
return AMDSMI_STATUS_OUT_OF_RESOURCES;
|
||||
}
|
||||
for (auto &pid : pids) {
|
||||
if (i >= *max_processes) {
|
||||
break;
|
||||
auto compute_process_list = gpu_device->amdgpu_get_compute_process_list();
|
||||
if ((*max_processes == 0) || compute_process_list.empty()) {
|
||||
*max_processes = static_cast<uint32_t>(compute_process_list.size());
|
||||
return amdsmi_status_t::AMDSMI_STATUS_SUCCESS;
|
||||
}
|
||||
if (!list) {
|
||||
return amdsmi_status_t::AMDSMI_STATUS_INVAL;
|
||||
}
|
||||
|
||||
const auto max_processes_original_size(*max_processes);
|
||||
auto idx = uint32_t(0);
|
||||
auto is_required_previlegies_required(false);
|
||||
for (auto& process : compute_process_list) {
|
||||
if (idx < *max_processes) {
|
||||
list[idx++] = static_cast<amdsmi_proc_info_t>(process.second);
|
||||
// Note: If we could not read the process info for an existing process,
|
||||
// that is likely a permission error.
|
||||
if (!is_required_previlegies_required && std::string(process.second.name).empty()) {
|
||||
is_required_previlegies_required = true;
|
||||
}
|
||||
list[i++] = (uint32_t)pid;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
*max_processes = (uint32_t)pids.size();
|
||||
}
|
||||
else {
|
||||
// rocm
|
||||
}
|
||||
|
||||
return AMDSMI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
amdsmi_status_t
|
||||
amdsmi_get_gpu_process_info(amdsmi_processor_handle processor_handle, amdsmi_process_handle_t process, amdsmi_proc_info_t *info) {
|
||||
AMDSMI_CHECK_INIT();
|
||||
|
||||
if (info == nullptr) {
|
||||
return AMDSMI_STATUS_INVAL;
|
||||
}
|
||||
|
||||
amd::smi::AMDSmiGPUDevice* gpu_device = nullptr;
|
||||
amdsmi_status_t r = get_gpu_device_from_handle(processor_handle, &gpu_device);
|
||||
if (r != AMDSMI_STATUS_SUCCESS)
|
||||
return r;
|
||||
|
||||
amdsmi_status_t status;
|
||||
if (gpu_device->check_if_drm_is_supported()) {
|
||||
status = gpuvsmi_get_pid_info(gpu_device->get_bdf(), process, *info);
|
||||
if (status != AMDSMI_STATUS_SUCCESS) return status;
|
||||
}
|
||||
else {
|
||||
// rocm
|
||||
}
|
||||
|
||||
return AMDSMI_STATUS_SUCCESS;
|
||||
// Note: If the reserved size for processes is smaller than the number of
|
||||
// actual processes running. The AMDSMI_STATUS_OUT_OF_RESOURCES is
|
||||
// an indication the caller should handle the situation (resize).
|
||||
// The max_processes is always changed to reflect the actual size of
|
||||
// list of processes running, so the caller knows where it is at.
|
||||
// Holding a copy of max_process before it is passed in will be helpful
|
||||
// for the caller.
|
||||
status_code = is_required_previlegies_required
|
||||
? amdsmi_status_t::AMDSMI_STATUS_NO_PERM : AMDSMI_STATUS_SUCCESS;
|
||||
*max_processes = static_cast<uint32_t>(compute_process_list.size());
|
||||
return (max_processes_original_size >= static_cast<uint32_t>(compute_process_list.size()))
|
||||
? status_code : amdsmi_status_t::AMDSMI_STATUS_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
amdsmi_status_t
|
||||
|
||||
@@ -41,10 +41,16 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <functional>
|
||||
#include "amd_smi/impl/amd_smi_gpu_device.h"
|
||||
#include "amd_smi/impl/amd_smi_common.h"
|
||||
#include "amd_smi/impl/fdinfo.h"
|
||||
#include "rocm_smi/rocm_smi_kfd.h"
|
||||
#include "rocm_smi/rocm_smi_utils.h"
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace amd {
|
||||
namespace smi {
|
||||
@@ -148,6 +154,153 @@ amdsmi_status_t AMDSmiGPUDevice::amdgpu_query_vbios(void *info) const {
|
||||
return drm_.amdgpu_query_vbios(fd, info);
|
||||
}
|
||||
|
||||
|
||||
int32_t AMDSmiGPUDevice::get_compute_process_list_impl(GPUComputeProcessList_t& compute_process_list,
|
||||
ComputeProcessListType_t list_type)
|
||||
{
|
||||
/**
|
||||
* The first call to GetProcessInfo() helps to find the size it needs,
|
||||
* so we can create a tailored size list.
|
||||
*/
|
||||
auto status_code(rsmi_status_t::RSMI_STATUS_SUCCESS);
|
||||
auto list_process_running_size = uint32_t(0);
|
||||
auto list_process_allocation_size = uint32_t(0);
|
||||
|
||||
status_code = rsmi_compute_process_info_get(nullptr, &list_process_running_size);
|
||||
if ((status_code != rsmi_status_t::RSMI_STATUS_SUCCESS) || (list_process_running_size <= 0)) {
|
||||
return status_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* The second call to GetProcessInfo() helps to set proper sizes for both,
|
||||
* the raw array of processes (amdsmi_process_info_t) and list of processes (amdsmi_proc_info_t).
|
||||
*/
|
||||
using RsmiDeviceList_t = uint32_t[];
|
||||
using RsmiProcessList_t = rsmi_process_info_t[];
|
||||
std::unique_ptr<RsmiProcessList_t> list_all_processes_ptr = std::make_unique<RsmiProcessList_t>(list_process_running_size);
|
||||
|
||||
list_process_allocation_size = list_process_running_size;
|
||||
status_code = rsmi_compute_process_info_get(list_all_processes_ptr.get(), &list_process_allocation_size);
|
||||
if (status_code) {
|
||||
return status_code;
|
||||
}
|
||||
|
||||
// Restore the original size to read
|
||||
list_process_running_size = list_process_allocation_size;
|
||||
if (list_process_running_size <= 0) {
|
||||
return rsmi_status_t::RSMI_STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Setup for the cases where the process list is by device.
|
||||
*/
|
||||
auto list_device_running_size = uint32_t(0);
|
||||
auto list_device_allocation_size = uint32_t(0);
|
||||
status_code = rsmi_num_monitor_devices(&list_device_running_size);
|
||||
if ((status_code != rsmi_status_t::RSMI_STATUS_SUCCESS) || (list_device_running_size <= 0)) {
|
||||
return status_code;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Complete the process information
|
||||
*/
|
||||
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);
|
||||
// If we cannot get the info from sysfs, save the minimum info
|
||||
if (status_code != amdsmi_status_t::AMDSMI_STATUS_SUCCESS) {
|
||||
asmi_proc_info.pid = rsmi_proc_info.process_id;
|
||||
asmi_proc_info.memory_usage.vram_mem = rsmi_proc_info.vram_usage;
|
||||
}
|
||||
|
||||
return status_code;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get process information
|
||||
*/
|
||||
auto update_list_by_running_process = [&](const uint32_t process_id) {
|
||||
auto status_result(true);
|
||||
rsmi_process_info_t rsmi_proc_info{};
|
||||
auto status_code = rsmi_compute_process_info_by_pid_get(process_id, &rsmi_proc_info);
|
||||
if (status_code != rsmi_status_t::RSMI_STATUS_SUCCESS) {
|
||||
status_result = false;
|
||||
return status_result;
|
||||
}
|
||||
|
||||
amdsmi_proc_info_t tmp_asmi_proc_info{};
|
||||
get_process_info(rsmi_proc_info, tmp_asmi_proc_info);
|
||||
compute_process_list.emplace(process_id, tmp_asmi_proc_info);
|
||||
|
||||
return status_result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Devices used by a process.
|
||||
*/
|
||||
auto update_list_by_running_device = [&](const uint32_t process_id,
|
||||
const uint32_t proc_addr_id) {
|
||||
// Get all devices running this process
|
||||
auto status_result(true);
|
||||
std::unique_ptr<RsmiDeviceList_t> list_device_ptr = std::make_unique<RsmiDeviceList_t>(list_device_running_size);
|
||||
list_device_allocation_size = list_device_running_size;
|
||||
auto status_code = rsmi_compute_process_gpus_get(process_id, list_device_ptr.get(), &list_device_allocation_size);
|
||||
if (status_code != rsmi_status_t::RSMI_STATUS_SUCCESS) {
|
||||
status_result = false;
|
||||
return status_result;
|
||||
}
|
||||
|
||||
for (auto device_idx = uint32_t(0); device_idx < list_device_allocation_size; ++device_idx) {
|
||||
// Is this device running this process?
|
||||
if (list_device_ptr[device_idx] == get_gpu_id()) {
|
||||
rsmi_process_info_t rsmi_dev_proc_info{};
|
||||
auto status_code = rsmi_compute_process_info_by_device_get(process_id, list_device_ptr[device_idx], &rsmi_dev_proc_info);
|
||||
if ((status_code == rsmi_status_t::RSMI_STATUS_SUCCESS) &&
|
||||
((rsmi_dev_proc_info.process_id == process_id) && (rsmi_dev_proc_info.pasid == proc_addr_id))) {
|
||||
amdsmi_proc_info_t tmp_asmi_proc_info{};
|
||||
get_process_info(rsmi_dev_proc_info, tmp_asmi_proc_info);
|
||||
compute_process_list.emplace(process_id, tmp_asmi_proc_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status_result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Transfer/Save the ones linked to this device.
|
||||
*/
|
||||
compute_process_list.clear();
|
||||
for (auto process_idx = uint32_t(0); process_idx < list_process_running_size; ++process_idx) {
|
||||
if (list_type == ComputeProcessListType_t::kAllProcesses) {
|
||||
if (update_list_by_running_process(list_all_processes_ptr[process_idx].process_id)) {
|
||||
}
|
||||
}
|
||||
|
||||
if (list_type == ComputeProcessListType_t::kAllProcessesOnDevice) {
|
||||
if (update_list_by_running_device(list_all_processes_ptr[process_idx].process_id,
|
||||
list_all_processes_ptr[process_idx].pasid)) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status_code;
|
||||
}
|
||||
|
||||
const GPUComputeProcessList_t& AMDSmiGPUDevice::amdgpu_get_compute_process_list(ComputeProcessListType_t list_type)
|
||||
{
|
||||
auto error_code = get_compute_process_list_impl(compute_process_list_, list_type);
|
||||
if (error_code) {
|
||||
compute_process_list_.clear();
|
||||
}
|
||||
|
||||
return compute_process_list_;
|
||||
}
|
||||
|
||||
|
||||
} // namespace smi
|
||||
} // namespace amd
|
||||
|
||||
|
||||
@@ -220,12 +220,10 @@ amdsmi_status_t gpuvsmi_get_pid_info(const amdsmi_bdf_t &bdf, long int pid,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
closedir(d);
|
||||
|
||||
if (!pasids.size())
|
||||
return AMDSMI_STATUS_NOT_FOUND;
|
||||
|
||||
// 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;
|
||||
|
||||
@@ -252,9 +250,12 @@ amdsmi_status_t gpuvsmi_get_pid_info(const amdsmi_bdf_t &bdf, long int pid,
|
||||
if (strlen(info.container_name) > 0)
|
||||
break;
|
||||
}
|
||||
|
||||
info.pid = (uint32_t)pid;
|
||||
|
||||
if (!pasids.size()) {
|
||||
return AMDSMI_STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
return AMDSMI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user