From ef78459f754dbc502cbb7db15f4fd2237e4ba6b2 Mon Sep 17 00:00:00 2001 From: "Bill(Shuzhou) Liu" Date: Mon, 12 Aug 2024 08:15:20 -0500 Subject: [PATCH 1/2] Set soft min or max clock Add the API to support set soft min or max clock. Change-Id: Ia34381a721ef3c3d894d5a89d25afa757be46a79 [ROCm/amdsmi commit: 97e70d44cf88ca29ced78dc298fedeaeb1718720] --- projects/amdsmi/include/amd_smi/amdsmi.h | 37 +++++++++++++ .../rocm_smi/include/rocm_smi/rocm_smi.h | 26 ++++++++++ projects/amdsmi/rocm_smi/src/rocm_smi.cc | 52 +++++++++++++++++++ projects/amdsmi/src/amd_smi/amd_smi.cc | 10 ++++ 4 files changed, 125 insertions(+) diff --git a/projects/amdsmi/include/amd_smi/amdsmi.h b/projects/amdsmi/include/amd_smi/amdsmi.h index 5a3ff936ab..82e72af16d 100644 --- a/projects/amdsmi/include/amd_smi/amdsmi.h +++ b/projects/amdsmi/include/amd_smi/amdsmi.h @@ -1003,6 +1003,15 @@ typedef enum { AMDSMI_GPU_BLOCK_RESERVED = 0x8000000000000000 } amdsmi_gpu_block_t; + +/** + * @brief The clk limit type + */ +typedef enum { + CLK_LIMIT_MIN, + CLK_LIMIT_MAX +} amdsmi_clk_limit_type_t; + /** * @brief The current ECC state */ @@ -3122,6 +3131,9 @@ amdsmi_status_t amdsmi_get_gpu_reg_table_info( * @brief This function sets the clock range information. It is not supported on virtual * machine guest * + * @deprecated ::amdsmi_set_gpu_clk_limit() should be used, with an + * interface that set the min_value and then max_value. + * * @platform{gpu_bm_linux} * * @details Given a processor handle @p processor_handle, a minimum clock value @p minclkvalue, @@ -3145,6 +3157,31 @@ amdsmi_status_t amdsmi_set_gpu_clk_range(amdsmi_processor_handle processor_handl uint64_t maxclkvalue, amdsmi_clk_type_t clkType); +/** + * @brief This function sets the clock sets the clock min/max level + * + * @platform{gpu_bm_linux} @platform{guest_1vf} + * + * @details Given a processor handle @p processor_handle, a clock type @p clk_type, + * a value @p clk_value needs to be set, and the @p level indicates min or max + * clock you want to set, this function the clock limit. + * + * @param[in] processor_handle a processor handle + * + * @param[in] clk_type AMDSMI_CLK_TYPE_SYS, AMDSMI_CLK_TYPE_MEM and so on + * + * @param[in] limit_type AMDSMI_FREQ_IND_MIN|AMDSMI_FREQ_IND_MAX to set the + * minimum (0) or maximum (1) speed. + * + * @param[in] clk_value value to apply to. Frequency values are in MHz. + * + * @return ::amdsmi_status_t | ::AMDSMI_STATUS_SUCCESS on success, non-zero on fail + */ +amdsmi_status_t amdsmi_set_gpu_clk_limit(amdsmi_processor_handle processor_handle, + amdsmi_clk_type_t clk_type, + amdsmi_clk_limit_type_t limit_type, + uint64_t clk_value); + /** * @brief This function sets the clock frequency information. It is not supported on * virtual machine guest diff --git a/projects/amdsmi/rocm_smi/include/rocm_smi/rocm_smi.h b/projects/amdsmi/rocm_smi/include/rocm_smi/rocm_smi.h index acbd678232..e53527b1ce 100755 --- a/projects/amdsmi/rocm_smi/include/rocm_smi/rocm_smi.h +++ b/projects/amdsmi/rocm_smi/include/rocm_smi/rocm_smi.h @@ -3033,6 +3033,32 @@ rsmi_status_t rsmi_dev_clk_range_set(uint32_t dv_ind, uint64_t minclkvalue, uint64_t maxclkvalue, rsmi_clk_type_t clkType); +/** + * @brief This function sets the clock min/max level + * + * @details Given a device index @p dv_ind, a clock value @p minclkvalue, + * a maximum clock value @p maxclkvalue and a clock type @p clkType this function + * will set the sclk|mclk range + * + * @param[in] dv_ind a device index + * + * @param[in] level RSMI_FREQ_IND_MIN|RSMI_FREQ_IND_MAX + * + * @param[in] clkvalue value to apply to the clock level. Frequency values + * are in MHz. + * + * @param[in] clkType RSMI_CLK_TYPE_SYS | RSMI_CLK_TYPE_MEM level type + * + * @retval ::RSMI_STATUS_SUCCESS call was successful + * @retval ::RSMI_STATUS_NOT_SUPPORTED installed software or hardware does not + * support this function with the given arguments + * @retval ::RSMI_STATUS_INVALID_ARGS the provided arguments are not valid + */ +rsmi_status_t rsmi_dev_clk_extremum_set(uint32_t dv_ind, rsmi_freq_ind_t level, + uint64_t clkvalue, + rsmi_clk_type_t clkType); + + /** * @brief This function sets the clock frequency information * diff --git a/projects/amdsmi/rocm_smi/src/rocm_smi.cc b/projects/amdsmi/rocm_smi/src/rocm_smi.cc index fd4ace7f9f..c38d97480a 100755 --- a/projects/amdsmi/rocm_smi/src/rocm_smi.cc +++ b/projects/amdsmi/rocm_smi/src/rocm_smi.cc @@ -1532,6 +1532,58 @@ static rsmi_status_t get_od_clk_volt_info(uint32_t dv_ind, CATCH } +rsmi_status_t rsmi_dev_clk_extremum_set(uint32_t dv_ind, rsmi_freq_ind_t level, + uint64_t clkvalue, + rsmi_clk_type_t clkType) { + TRY + rsmi_status_t ret; + std::ostringstream ss; + ss << __PRETTY_FUNCTION__ << "| ======= start ======="; + LOG_TRACE(ss); + + if (clkType != RSMI_CLK_TYPE_SYS && clkType != RSMI_CLK_TYPE_MEM) { + return RSMI_STATUS_INVALID_ARGS; + } + if (level != RSMI_FREQ_IND_MIN && level != RSMI_FREQ_IND_MAX) { + return RSMI_STATUS_INVALID_ARGS; + } + + std::map clk_char_map = { + {RSMI_CLK_TYPE_SYS, "s"}, + {RSMI_CLK_TYPE_MEM, "m"}, + }; + DEVICE_MUTEX + + // Set perf. level to manual so that we can then set the power profile + ret = rsmi_dev_perf_level_set_v1(dv_ind, RSMI_DEV_PERF_LEVEL_MANUAL); + if (ret != RSMI_STATUS_SUCCESS) { + return ret; + } + // For clock frequency setting, enter a new value by writing a string that + // contains "s/m index clock" to the file. The index should be 0 if to set + // minimum clock. And 1 if to set maximum clock. E.g., "s 0 500" will update + // minimum sclk to be 500 MHz. "m 1 800" will update maximum mclk to 800Mhz. + + std::string sysvalue = clk_char_map[clkType]; + sysvalue += ' ' + std::to_string(level); + sysvalue += ' ' + std::to_string(clkvalue); + sysvalue += '\n'; + + ret = set_dev_range(dv_ind, sysvalue); + if (ret != RSMI_STATUS_SUCCESS) { + return ret; + } + + ret = set_dev_range(dv_ind, "c"); + if (ret != RSMI_STATUS_SUCCESS) { + return ret; + } + + return RSMI_STATUS_SUCCESS; + CATCH +} + + rsmi_status_t rsmi_dev_clk_range_set(uint32_t dv_ind, uint64_t minclkvalue, uint64_t maxclkvalue, rsmi_clk_type_t clkType) { diff --git a/projects/amdsmi/src/amd_smi/amd_smi.cc b/projects/amdsmi/src/amd_smi/amd_smi.cc index 0ae2114762..794d79a697 100644 --- a/projects/amdsmi/src/amd_smi/amd_smi.cc +++ b/projects/amdsmi/src/amd_smi/amd_smi.cc @@ -1552,6 +1552,16 @@ amdsmi_status_t amdsmi_set_gpu_clk_range(amdsmi_processor_handle processor_handl static_cast(clkType)); } +amdsmi_status_t amdsmi_set_gpu_clk_limit(amdsmi_processor_handle processor_handle, + amdsmi_clk_type_t clk_type, + amdsmi_clk_limit_type_t limit_type, + uint64_t clk_value) { + return rsmi_wrapper(rsmi_dev_clk_extremum_set, processor_handle, + static_cast(limit_type), + clk_value, + static_cast(clk_type)); +} + amdsmi_status_t amdsmi_reset_gpu(amdsmi_processor_handle processor_handle) { return rsmi_wrapper(rsmi_dev_gpu_reset, processor_handle); } From c59f7b7705f47c51808a6aa218be6ce4e863e881 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Thu, 1 Aug 2024 10:49:04 -0400 Subject: [PATCH 2/2] Add amdsmi_get_gpu_pm_metrics_info and amdsmi_get_gpu_reg_table_info to py-interface (v3) v2: drop depend on libc v3: whitespace Signed-off-by: Tom St Denis Change-Id: I2eff7aa9d4f0ca8635796f82b106ac0d36176346 [ROCm/amdsmi commit: f4506cfd65efeb47db910f5f27e8d9ff61a6f598] --- projects/amdsmi/include/amd_smi/amdsmi.h | 12 +++++ .../amdsmi/py-interface/amdsmi_interface.py | 54 +++++++++++++++++++ .../amdsmi/py-interface/amdsmi_wrapper.py | 32 ++++++----- projects/amdsmi/src/amd_smi/amd_smi.cc | 4 ++ 4 files changed, 88 insertions(+), 14 deletions(-) diff --git a/projects/amdsmi/include/amd_smi/amdsmi.h b/projects/amdsmi/include/amd_smi/amdsmi.h index 82e72af16d..1fd022bd2c 100644 --- a/projects/amdsmi/include/amd_smi/amdsmi.h +++ b/projects/amdsmi/include/amd_smi/amdsmi.h @@ -3182,6 +3182,18 @@ amdsmi_status_t amdsmi_set_gpu_clk_limit(amdsmi_processor_handle processor_handl amdsmi_clk_limit_type_t limit_type, uint64_t clk_value); +/** + * @brief Frees heap memory allocated by reg_table and pm_metrics + * + * @platform{gpu_bm_linux} + * + * @details Frees heap memory. + * + * @param[in] p a pointer to the memory to free. + * + */ +void amdsmi_free_name_value_pairs(void *p); + /** * @brief This function sets the clock frequency information. It is not supported on * virtual machine guest diff --git a/projects/amdsmi/py-interface/amdsmi_interface.py b/projects/amdsmi/py-interface/amdsmi_interface.py index 1b3cb3ec6d..7463a2284f 100644 --- a/projects/amdsmi/py-interface/amdsmi_interface.py +++ b/projects/amdsmi/py-interface/amdsmi_interface.py @@ -1693,6 +1693,60 @@ def amdsmi_get_power_cap_info( "min_power_cap": power_info.min_power_cap, "max_power_cap": power_info.max_power_cap} +def amdsmi_get_gpu_pm_metrics_info( + processor_handle: amdsmi_wrapper.amdsmi_processor_handle, +) -> Dict[str, Any]: + if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle): + raise AmdSmiParameterException( + processor_handle, amdsmi_wrapper.amdsmi_processor_handle + ) + + pm_metrics = ctypes.POINTER(struct_amdsmi_name_value_t); + num_mets = ctypes.c_uint32; + + _check_res( + amdsmi_wrapper.amdsmi_get_gpu_pm_metrics_info( + processor_handle, ctypes.byref(pm_metrics), ctypes.byref(num_mets) + ) + ) + + results = [] + for i in range(num_mets.value): + item = { + 'name': pm_metrics[i].name, + 'value': pm_metrics[i].value + } + results.append(item) + amdsmi_wrapper.amdsmi_free_name_value_pairs(pm_metrics) + return results + +def amdsmi_get_gpu_reg_table_info( + processor_handle: amdsmi_wrapper.amdsmi_processor_handle, + reg_type: amdsmi_reg_type_t, +) -> Dict[str, Any]: + if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle): + raise AmdSmiParameterException( + processor_handle, amdsmi_wrapper.amdsmi_processor_handle + ) + + reg_metrics = ctypes.POINTER(struct_amdsmi_name_value_t); + num_regs = ctypes.c_uint32; + + _check_res( + amdsmi_wrapper.amdsmi_get_cpu_reg_table_info( + processor_handle, reg_type, ctypes.byref(reg_metrics), ctypes.byref(num_regs) + ) + ) + + results = [] + for i in range(num_regs.value): + item = { + 'name': reg_metrics[i].name, + 'value': reg_metrics[i].value + } + results.append(item) + amdsmi_wrapper.amdsmi_free_name_value_pairs(pm_metrics) + return results def amdsmi_get_gpu_vram_info( processor_handle: amdsmi_wrapper.amdsmi_processor_handle, diff --git a/projects/amdsmi/py-interface/amdsmi_wrapper.py b/projects/amdsmi/py-interface/amdsmi_wrapper.py index 870512ccdb..5aa163656a 100644 --- a/projects/amdsmi/py-interface/amdsmi_wrapper.py +++ b/projects/amdsmi/py-interface/amdsmi_wrapper.py @@ -759,6 +759,19 @@ 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), + ('reserved', ctypes.c_uint64 * 10), +] + class struct_pcie_metric_(Structure): pass @@ -777,19 +790,6 @@ struct_pcie_metric_._fields_ = [ ('reserved', ctypes.c_uint64 * 13), ] -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), - ('reserved', ctypes.c_uint64 * 10), -] - struct_amdsmi_pcie_info_t._pack_ = 1 # source:False struct_amdsmi_pcie_info_t._fields_ = [ ('pcie_static', struct_pcie_static_), @@ -2061,6 +2061,9 @@ amdsmi_get_gpu_reg_table_info.argtypes = [amdsmi_processor_handle, amdsmi_reg_ty amdsmi_set_gpu_clk_range = _libraries['libamd_smi.so'].amdsmi_set_gpu_clk_range amdsmi_set_gpu_clk_range.restype = amdsmi_status_t amdsmi_set_gpu_clk_range.argtypes = [amdsmi_processor_handle, uint64_t, uint64_t, amdsmi_clk_type_t] +amdsmi_free_name_value_pairs = _libraries['libamd_smi.so'].amdsmi_free_name_value_pairs +amdsmi_free_name_value_pairs.restype = None +amdsmi_free_name_value_pairs.argtypes = [ctypes.POINTER(None)] amdsmi_set_gpu_od_clk_info = _libraries['libamd_smi.so'].amdsmi_set_gpu_od_clk_info amdsmi_set_gpu_od_clk_info.restype = amdsmi_status_t amdsmi_set_gpu_od_clk_info.argtypes = [amdsmi_processor_handle, amdsmi_freq_ind_t, uint64_t, amdsmi_clk_type_t] @@ -2597,7 +2600,8 @@ __all__ = \ 'amdsmi_event_group_t', 'amdsmi_event_handle_t', 'amdsmi_event_type_t', 'amdsmi_evt_notification_data_t', 'amdsmi_evt_notification_type_t', - 'amdsmi_first_online_core_on_cpu_socket', 'amdsmi_freq_ind_t', + 'amdsmi_first_online_core_on_cpu_socket', + 'amdsmi_free_name_value_pairs', 'amdsmi_freq_ind_t', 'amdsmi_freq_volt_region_t', 'amdsmi_frequencies_t', 'amdsmi_frequency_range_t', 'amdsmi_fw_block_t', 'amdsmi_fw_info_t', 'amdsmi_get_clk_freq', diff --git a/projects/amdsmi/src/amd_smi/amd_smi.cc b/projects/amdsmi/src/amd_smi/amd_smi.cc index 794d79a697..8e0905b5b2 100644 --- a/projects/amdsmi/src/amd_smi/amd_smi.cc +++ b/projects/amdsmi/src/amd_smi/amd_smi.cc @@ -1217,6 +1217,10 @@ amdsmi_status_t amdsmi_get_gpu_reg_table_info( num_of_metrics); } +void amdsmi_free_name_value_pairs(void *p) { + free(p); +} + amdsmi_status_t amdsmi_get_power_cap_info(amdsmi_processor_handle processor_handle, uint32_t sensor_ind,