diff --git a/projects/amdsmi/CHANGELOG.md b/projects/amdsmi/CHANGELOG.md index 6006d2ca7a..4bfe6fa24d 100644 --- a/projects/amdsmi/CHANGELOG.md +++ b/projects/amdsmi/CHANGELOG.md @@ -8,6 +8,10 @@ Full documentation for amd_smi_lib is available at [https://rocm.docs.amd.com/pr ### Added +- **Added cpu model name for RDC**. + - Added new C and Python API `amdsmi_get_cpu_model_name` + - Not sourced from esmi library. + - **Added support for GPU metrics 1.8**. - Added new fields for `amdsmi_gpu_xcp_metrics_t` including: - Adding the following metrics to allow new calculations for violation status: @@ -22,6 +26,7 @@ Full documentation for amd_smi_lib is available at [https://rocm.docs.amd.com/pr - **Added Power Cap to amd-smi monitor**. - 'amd-smi monitor -p' will display the power cap along with power. + ```shell $ amd-smi monitor -p GPU POWER PWR_CAP diff --git a/projects/amdsmi/docs/reference/amdsmi-py-api.md b/projects/amdsmi/docs/reference/amdsmi-py-api.md index 8e5fb2e155..9a5459461b 100644 --- a/projects/amdsmi/docs/reference/amdsmi-py-api.md +++ b/projects/amdsmi/docs/reference/amdsmi-py-api.md @@ -5127,6 +5127,26 @@ except AmdSmiException as e: print(e) ``` +### amdsmi_get_cpu_model_name + +Description: Get cpu model name. + +Output: cpu model name + +Exceptions that can be thrown by `amdsmi_get_cpu_model_name` function: + +* `AmdSmiLibraryException` + +Example: + +```python +try: + cpu_model_name = amdsmi_get_cpu_model_name() + print(cpu_model_name) +except AmdSmiException as e: + print(e) +``` + ## No amdsmi_init APIs ### amdsmi_get_lib_version diff --git a/projects/amdsmi/include/amd_smi/amdsmi.h b/projects/amdsmi/include/amd_smi/amdsmi.h index 0e5dcad53d..e38568abb2 100644 --- a/projects/amdsmi/include/amd_smi/amdsmi.h +++ b/projects/amdsmi/include/amd_smi/amdsmi.h @@ -34,9 +34,6 @@ #ifdef __cplusplus extern "C" { #include -#ifdef ENABLE_ESMI_LIB - #include -#endif #else // __cplusplus #include #endif // __cplusplus @@ -935,6 +932,19 @@ typedef enum { AMDSMI_LINK_TYPE_UNKNOWN } amdsmi_link_type_t; +/** + * @brief This structure holds CPU utilization information. + * + * @cond @tag{cpu_bm} @endcond + */ +typedef struct { + uint32_t cpu_util_total; + uint32_t cpu_util_user; + uint32_t cpu_util_nice; + uint32_t cpu_util_sys; + uint32_t cpu_util_irq; +} amdsmi_cpu_util_t; + /** * @brief Link Metrics * @@ -2221,6 +2231,32 @@ static char* const amdsmi_hsmp_freqlimit_src_names[] = { "HSMP Agent" }; +/** + * @brief cpu info data + * + * @cond @tag{cpu_bm} @endcond + */ +typedef struct { + char model_name[AMDSMI_MAX_STRING_LENGTH]; + uint32_t cpu_family_id; + uint32_t model_id; + uint32_t threads_per_core; + uint32_t cores_per_socket; + bool frequency_boost; + uint32_t vendor_id; //< Use 32 bit to be compatible with other platform. + char vendor_name[AMDSMI_MAX_STRING_LENGTH]; + uint32_t subvendor_id; //< The subsystem vendor id + uint64_t device_id; //< The device id of a GPU + uint32_t rev_id; + char asic_serial[AMDSMI_MAX_STRING_LENGTH]; + uint32_t socket_id; //< 0xFFFF if not supported + uint32_t core_id; + uint32_t num_of_cpu_cores; //< 0xFFFFFFFF if not supported + uint32_t socket_count; + uint32_t core_count; + uint32_t reserved[17]; +} amdsmi_cpu_info_t; + #endif /*****************************************************************************/ @@ -2437,6 +2473,7 @@ amdsmi_status_t amdsmi_get_processor_handles_by_type(amdsmi_socket_handle socket processor_type_t processor_type, amdsmi_processor_handle* processor_handles, uint32_t* processor_count); + #endif /** @@ -6805,6 +6842,30 @@ amdsmi_status_t amdsmi_get_cpu_family(uint32_t *cpu_family); */ amdsmi_status_t amdsmi_get_cpu_model(uint32_t *cpu_model); + /** + * @brief Retrieve the CPU processor model name based on the processor index. + * + * @platform{cpu_bm} + * + * @details + * This function obtains the CPU model name associated with the specified processor index + * from the list of available processor handles. Before invoking this function, ensure that + * the list of processor handles is properly initialized and that the processor type is specified. + * This function is to be utilized for RDC and is not part of ESMI library. + * + * @param[in] processor_handle Cpu socket which to query + * + * @param[out] cpu_info + * A pointer to an `amdsmi_cpu_info_t` structure that will be populated with the + * CPU processor model information upon successful execution of the function. + * + * @return + * ::amdsmi_status_t indicating the result of the operation. + * - ::AMDSMI_STATUS_SUCCESS on successful retrieval of the model name. + * - A non-zero error code if the operation fails. + */ +amdsmi_status_t amdsmi_get_cpu_model_name(amdsmi_processor_handle processor_handle, amdsmi_cpu_info_t *cpu_info); + /** * @brief Get a description of provided AMDSMI error status for esmi errors. * diff --git a/projects/amdsmi/include/amd_smi/impl/amd_smi_common.h b/projects/amdsmi/include/amd_smi/impl/amd_smi_common.h index cf79277467..1c679b2a3b 100644 --- a/projects/amdsmi/include/amd_smi/impl/amd_smi_common.h +++ b/projects/amdsmi/include/amd_smi/impl/amd_smi_common.h @@ -27,6 +27,13 @@ #include "rocm_smi/rocm_smi.h" #include "amd_smi/amdsmi.h" +#ifdef ENABLE_ESMI_LIB +extern "C" { + #include + #include +} +#endif + namespace amd { namespace smi { diff --git a/projects/amdsmi/include/amd_smi/impl/amd_smi_system.h b/projects/amdsmi/include/amd_smi/impl/amd_smi_system.h index e469c26263..a8dddb287e 100644 --- a/projects/amdsmi/include/amd_smi/impl/amd_smi_system.h +++ b/projects/amdsmi/include/amd_smi/impl/amd_smi_system.h @@ -61,7 +61,8 @@ class AMDSmiSystem { amdsmi_status_t clean_up_drm() { return drm_.cleanup();} amdsmi_status_t init_drm() { return drm_.init();} - + + amdsmi_status_t get_cpu_model_name(uint32_t socket_id, std::string *model_name); private: AMDSmiSystem() : init_flag_(AMDSMI_INIT_AMD_GPUS) {} diff --git a/projects/amdsmi/py-interface/__init__.py b/projects/amdsmi/py-interface/__init__.py index 1148cd2f42..2023380ba7 100644 --- a/projects/amdsmi/py-interface/__init__.py +++ b/projects/amdsmi/py-interface/__init__.py @@ -77,6 +77,7 @@ try: from .amdsmi_interface import amdsmi_first_online_core_on_cpu_socket from .amdsmi_interface import amdsmi_get_cpu_family from .amdsmi_interface import amdsmi_get_cpu_model + from .amdsmi_interface import amdsmi_get_cpu_model_name except AttributeError: pass diff --git a/projects/amdsmi/py-interface/amdsmi_interface.py b/projects/amdsmi/py-interface/amdsmi_interface.py index c3dfaacd0a..aff501458a 100644 --- a/projects/amdsmi/py-interface/amdsmi_interface.py +++ b/projects/amdsmi/py-interface/amdsmi_interface.py @@ -1676,6 +1676,23 @@ def amdsmi_get_cpu_model(): ) return model.value +def amdsmi_get_cpu_model_name( + processor_handle: amdsmi_wrapper.amdsmi_processor_handle +): + if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle): + raise AmdSmiParameterException( + processor_handle, amdsmi_wrapper.amdsmi_processor_handle + ) + + cpu_info = amdsmi_wrapper.amdsmi_cpu_info_t() + + _check_res( + amdsmi_wrapper.amdsmi_get_cpu_model_name( + processor_handle, cpu_info + ) + ) + return f"{cpu_info.model_name}" + def amdsmi_init(flag=AmdSmiInitFlags.INIT_AMD_GPUS): if not isinstance(flag, AmdSmiInitFlags): raise AmdSmiParameterException(flag, AmdSmiInitFlags) diff --git a/projects/amdsmi/py-interface/amdsmi_wrapper.py b/projects/amdsmi/py-interface/amdsmi_wrapper.py index 576fc5a8ea..e39bd3e881 100644 --- a/projects/amdsmi/py-interface/amdsmi_wrapper.py +++ b/projects/amdsmi/py-interface/amdsmi_wrapper.py @@ -856,6 +856,21 @@ amdsmi_card_form_factor_t = ctypes.c_uint32 # enum class struct_amdsmi_pcie_info_t(Structure): pass +class struct_pcie_static_(Structure): + pass + +struct_pcie_static_._pack_ = 1 # source:False +struct_pcie_static_._fields_ = [ + ('max_pcie_width', ctypes.c_uint16), + ('PADDING_0', ctypes.c_ubyte * 2), + ('max_pcie_speed', ctypes.c_uint32), + ('pcie_interface_version', ctypes.c_uint32), + ('slot_type', amdsmi_card_form_factor_t), + ('max_pcie_interface_version', ctypes.c_uint32), + ('PADDING_1', ctypes.c_ubyte * 4), + ('reserved', ctypes.c_uint64 * 9), +] + class struct_pcie_metric_(Structure): pass @@ -876,21 +891,6 @@ struct_pcie_metric_._fields_ = [ ('reserved', ctypes.c_uint64 * 12), ] -class struct_pcie_static_(Structure): - pass - -struct_pcie_static_._pack_ = 1 # source:False -struct_pcie_static_._fields_ = [ - ('max_pcie_width', ctypes.c_uint16), - ('PADDING_0', ctypes.c_ubyte * 2), - ('max_pcie_speed', ctypes.c_uint32), - ('pcie_interface_version', ctypes.c_uint32), - ('slot_type', amdsmi_card_form_factor_t), - ('max_pcie_interface_version', ctypes.c_uint32), - ('PADDING_1', ctypes.c_ubyte * 4), - ('reserved', ctypes.c_uint64 * 9), -] - struct_amdsmi_pcie_info_t._pack_ = 1 # source:False struct_amdsmi_pcie_info_t._fields_ = [ ('pcie_static', struct_pcie_static_), @@ -1127,6 +1127,19 @@ AMDSMI_LINK_TYPE_PCIE = 2 AMDSMI_LINK_TYPE_NOT_APPLICABLE = 3 AMDSMI_LINK_TYPE_UNKNOWN = 4 amdsmi_link_type_t = ctypes.c_uint32 # enum +class struct_amdsmi_cpu_util_t(Structure): + pass + +struct_amdsmi_cpu_util_t._pack_ = 1 # source:False +struct_amdsmi_cpu_util_t._fields_ = [ + ('cpu_util_total', ctypes.c_uint32), + ('cpu_util_user', ctypes.c_uint32), + ('cpu_util_nice', ctypes.c_uint32), + ('cpu_util_sys', ctypes.c_uint32), + ('cpu_util_irq', ctypes.c_uint32), +] + +amdsmi_cpu_util_t = struct_amdsmi_cpu_util_t class struct_amdsmi_link_metrics_t(Structure): pass @@ -2216,6 +2229,35 @@ struct_amdsmi_hsmp_metrics_table_t._fields_ = [ amdsmi_hsmp_metrics_table_t = struct_amdsmi_hsmp_metrics_table_t amdsmi_hsmp_freqlimit_src_names = ['cHTC-Active', 'PROCHOT', 'TDC limit', 'PPT Limit', 'OPN Max', 'Reliability Limit', 'APML Agent', 'HSMP Agent'] # Variable ctypes.POINTER(ctypes.c_char) * 8 +class struct_amdsmi_cpu_info_t(Structure): + pass + +struct_amdsmi_cpu_info_t._pack_ = 1 # source:False +struct_amdsmi_cpu_info_t._fields_ = [ + ('model_name', ctypes.c_char * 256), + ('cpu_family_id', ctypes.c_uint32), + ('model_id', ctypes.c_uint32), + ('threads_per_core', ctypes.c_uint32), + ('cores_per_socket', ctypes.c_uint32), + ('frequency_boost', ctypes.c_bool), + ('PADDING_0', ctypes.c_ubyte * 3), + ('vendor_id', ctypes.c_uint32), + ('vendor_name', ctypes.c_char * 256), + ('subvendor_id', ctypes.c_uint32), + ('PADDING_1', ctypes.c_ubyte * 4), + ('device_id', ctypes.c_uint64), + ('rev_id', ctypes.c_uint32), + ('asic_serial', ctypes.c_char * 256), + ('socket_id', ctypes.c_uint32), + ('core_id', ctypes.c_uint32), + ('num_of_cpu_cores', ctypes.c_uint32), + ('socket_count', ctypes.c_uint32), + ('core_count', ctypes.c_uint32), + ('reserved', ctypes.c_uint32 * 17), + ('PADDING_2', ctypes.c_ubyte * 4), +] + +amdsmi_cpu_info_t = struct_amdsmi_cpu_info_t uint64_t = ctypes.c_uint64 amdsmi_init = _libraries['libamd_smi.so'].amdsmi_init amdsmi_init.restype = amdsmi_status_t @@ -2748,6 +2790,9 @@ amdsmi_get_cpu_family.argtypes = [ctypes.POINTER(ctypes.c_uint32)] amdsmi_get_cpu_model = _libraries['libamd_smi.so'].amdsmi_get_cpu_model amdsmi_get_cpu_model.restype = amdsmi_status_t amdsmi_get_cpu_model.argtypes = [ctypes.POINTER(ctypes.c_uint32)] +amdsmi_get_cpu_model_name = _libraries['libamd_smi.so'].amdsmi_get_cpu_model_name +amdsmi_get_cpu_model_name.restype = amdsmi_status_t +amdsmi_get_cpu_model_name.argtypes = [amdsmi_processor_handle, ctypes.POINTER(struct_amdsmi_cpu_info_t)] amdsmi_get_esmi_err_msg = _libraries['libamd_smi.so'].amdsmi_get_esmi_err_msg amdsmi_get_esmi_err_msg.restype = amdsmi_status_t amdsmi_get_esmi_err_msg.argtypes = [amdsmi_status_t, ctypes.POINTER(ctypes.POINTER(ctypes.c_char))] @@ -2978,6 +3023,7 @@ __all__ = \ 'amdsmi_compute_partition_type_t', 'amdsmi_container_types_t', 'amdsmi_counter_command_t', 'amdsmi_counter_value_t', 'amdsmi_cpu_apb_disable', 'amdsmi_cpu_apb_enable', + 'amdsmi_cpu_info_t', 'amdsmi_cpu_util_t', 'amdsmi_cpusocket_handle', 'amdsmi_ddr_bw_metrics_t', 'amdsmi_dev_perf_level_t', 'amdsmi_dimm_power_t', 'amdsmi_dimm_thermal_t', 'amdsmi_dpm_level_t', @@ -3004,7 +3050,7 @@ __all__ = \ 'amdsmi_get_cpu_fclk_mclk', 'amdsmi_get_cpu_handles', 'amdsmi_get_cpu_hsmp_driver_version', 'amdsmi_get_cpu_hsmp_proto_ver', 'amdsmi_get_cpu_model', - 'amdsmi_get_cpu_prochot_status', + 'amdsmi_get_cpu_model_name', 'amdsmi_get_cpu_prochot_status', 'amdsmi_get_cpu_pwr_svi_telemetry_all_rails', 'amdsmi_get_cpu_smu_fw_version', 'amdsmi_get_cpu_socket_c0_residency', @@ -3146,6 +3192,7 @@ __all__ = \ 'struct_amdsmi_accelerator_partition_resource_profile_t', 'struct_amdsmi_asic_info_t', 'struct_amdsmi_board_info_t', 'struct_amdsmi_clk_info_t', 'struct_amdsmi_counter_value_t', + 'struct_amdsmi_cpu_info_t', 'struct_amdsmi_cpu_util_t', 'struct_amdsmi_ddr_bw_metrics_t', 'struct_amdsmi_dimm_power_t', 'struct_amdsmi_dimm_thermal_t', 'struct_amdsmi_dpm_level_t', 'struct_amdsmi_dpm_policy_entry_t', 'struct_amdsmi_dpm_policy_t', diff --git a/projects/amdsmi/src/amd_smi/amd_smi.cc b/projects/amdsmi/src/amd_smi/amd_smi.cc index 3afd5ae1ab..c8896f80c9 100644 --- a/projects/amdsmi/src/amd_smi/amd_smi.cc +++ b/projects/amdsmi/src/amd_smi/amd_smi.cc @@ -1520,6 +1520,7 @@ amdsmi_status_t amdsmi_get_gpu_vendor_name( name, len); } + amdsmi_status_t amdsmi_get_gpu_vram_vendor(amdsmi_processor_handle processor_handle, char *brand, uint32_t len) { return rsmi_wrapper(rsmi_dev_vram_vendor_get, processor_handle, 0, @@ -5224,6 +5225,30 @@ amdsmi_status_t amdsmi_get_cpu_model(uint32_t *cpu_model) return AMDSMI_STATUS_SUCCESS; } +amdsmi_status_t amdsmi_get_cpu_model_name(amdsmi_processor_handle processor_handle, amdsmi_cpu_info_t *cpu_info) +{ + amdsmi_status_t status; + uint32_t sock_ind; + std::string model_name; + + if (processor_handle == nullptr) + return AMDSMI_STATUS_INVAL; + + amdsmi_status_t r = amdsmi_get_processor_info(processor_handle, SIZE, proc_id); + if (r != AMDSMI_STATUS_SUCCESS) + return r; + + sock_ind = (uint8_t)std::stoi(proc_id, NULL, 0); + + status = amd::smi::AMDSmiSystem::getInstance().get_cpu_model_name(sock_ind, &model_name); + if (status != AMDSMI_STATUS_SUCCESS) + return amdsmi_errno_to_esmi_status(status); + + strncpy(cpu_info->model_name, model_name.c_str(), AMDSMI_MAX_STRING_LENGTH -1); + + return AMDSMI_STATUS_SUCCESS; +} + amdsmi_status_t amdsmi_get_cpu_handles(uint32_t *cpu_count, amdsmi_processor_handle *processor_handles) { @@ -5349,4 +5374,5 @@ amdsmi_status_t amdsmi_get_esmi_err_msg(amdsmi_status_t status, const char **sta } return AMDSMI_STATUS_SUCCESS; } + #endif diff --git a/projects/amdsmi/src/amd_smi/amd_smi_system.cc b/projects/amdsmi/src/amd_smi/amd_smi_system.cc index d0e1802271..d76fa21b2a 100644 --- a/projects/amdsmi/src/amd_smi/amd_smi_system.cc +++ b/projects/amdsmi/src/amd_smi/amd_smi_system.cc @@ -29,6 +29,9 @@ #include "amd_smi/impl/amd_smi_utils.h" #include "rocm_smi/rocm_smi.h" #include "rocm_smi/rocm_smi_main.h" +#include +#include +#include namespace amd { namespace smi { @@ -92,24 +95,59 @@ static amdsmi_status_t get_nr_cpu_sockets(uint32_t *num_socks) { } return AMDSMI_STATUS_SUCCESS; } + +amdsmi_status_t AMDSmiSystem::get_cpu_model_name(uint32_t socket_id, std::string *model_name) { + std::ifstream cpu_info("/proc/cpuinfo"); + std::string info; + std::map socket_model_map; + + if (!cpu_info.is_open()) { + std::cerr << "Failed to open /proc/cpuinfo:" << strerror(errno) << std::endl; + return AMDSMI_STATUS_FILE_ERROR; + } else { + uint32_t current_socket_id = -1; + while (std::getline(cpu_info, info)) { + if (info.find("processor") != std::string::npos) { + current_socket_id = std::stoi(info.substr(info.find(':') + 1)); + } + if (info.find("model name") != std::string::npos) { + *model_name = info.substr(info.find(':') + 2); + if (current_socket_id != -1) { + socket_model_map[current_socket_id] = *model_name; + } + } + } + cpu_info.close(); + } + + if (socket_model_map.find(socket_id) != socket_model_map.end()) { + *model_name = socket_model_map[socket_id]; + } else { + return AMDSMI_STATUS_NO_DATA; + } + return AMDSMI_STATUS_SUCCESS; +} #endif amdsmi_status_t AMDSmiSystem::init(uint64_t flags) { init_flag_ = flags; amdsmi_status_t amd_smi_status; - // populate sockets and processors + + // populate GPU sockets and processors if (flags & AMDSMI_INIT_AMD_GPUS) { amd_smi_status = populate_amd_gpu_devices(); if (amd_smi_status != AMDSMI_STATUS_SUCCESS) return amd_smi_status; } #ifdef ENABLE_ESMI_LIB + // populate CPU sockets and processors if (flags & AMDSMI_INIT_AMD_CPUS) { amd_smi_status = populate_amd_cpus(); if (amd_smi_status != AMDSMI_STATUS_SUCCESS) return amd_smi_status; } #endif + return AMDSMI_STATUS_SUCCESS; }