From 35196b25bdc97aef2d66a68a4e6538e4c32f55ac Mon Sep 17 00:00:00 2001 From: Dalibor Stanisavljevic Date: Wed, 9 Nov 2022 15:21:42 +0100 Subject: [PATCH] SWDEV-361376 - Added additional API calls to the python interface - Added APIs for "Supported Function Checks" - Added first half of the APIs for "Unsupported Functions In Virtual Environment" Change-Id: Ia83303e6b7ae65aada608bd9ca5f56fd33e4ef34 Signed-off-by: Dalibor Stanisavljevic [ROCm/amdsmi commit: a6efdd32ed238896a638079676a3028c5372e94b] --- projects/amdsmi/py-interface/README.md | 359 ++++++++++++++++++ projects/amdsmi/py-interface/__init__.py | 17 + .../amdsmi/py-interface/amdsmi_interface.py | 260 ++++++++++++- 3 files changed, 633 insertions(+), 3 deletions(-) diff --git a/projects/amdsmi/py-interface/README.md b/projects/amdsmi/py-interface/README.md index 86b37ea9d6..e463e48e48 100644 --- a/projects/amdsmi/py-interface/README.md +++ b/projects/amdsmi/py-interface/README.md @@ -1132,3 +1132,362 @@ except SmiException as e: Description: Detroys event listener object, closes all open files and directories Input parameters: `None` + + +## amdsmi_dev_supported_func_iterator_open +Description: Get a function name iterator of supported AMDSMI functions for a device + +Input parameters: + +* `device_handle` device which to query + +Output: Handle for a function iterator + +Exceptions that can be thrown by `amdsmi_dev_supported_func_iterator_open` function: +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: +```python +try: + devices = amdsmi_get_device_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + for device in devices: + obj_handle = amdsmi_dev_supported_func_iterator_open(device) + print(obj_handle) + amdsmi_dev_supported_func_iterator_close(obj_handle) +except AmdSmiException as e: + print(e) +``` + +## amdsmi_dev_supported_variant_iterator_open +Description: Get a variant iterator for a given handle + +Input parameters: + +* `obj_handle` Object handle for witch to return a variant handle + +Output: Variant iterator handle + +Exceptions that can be thrown by `amdsmi_dev_supported_variant_iterator_open` function: +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: +```python +try: + devices = amdsmi_get_device_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + for device in devices: + obj_handle = amdsmi_dev_supported_func_iterator_open(device) + var_iter = amdsmi_dev_supported_variant_iterator_open(obj_handle) + print(var_iter) + amdsmi_dev_supported_func_iterator_close(obj_handle) + amdsmi_dev_supported_func_iterator_close(var_iter) +except AmdSmiException as e: + print(e) +``` + +## amdsmi_func_iter_next +Description: Advance an object identifier iterator + +Input parameters: + +* `obj_handle` Object handle to advance + +Output: Next iterator handle + +Exceptions that can be thrown by `amdsmi_func_iter_next` function: +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: +```python +try: + devices = amdsmi_get_device_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + for device in devices: + obj_handle = amdsmi_dev_supported_func_iterator_open(device) + print(obj_handle) + obj_handle = amdsmi_func_iter_next(obj_handle) + print(obj_handle) + amdsmi_dev_supported_func_iterator_close(obj_handle) +except AmdSmiException as e: + print(e) +``` + +## amdsmi_dev_supported_func_iterator_close +Description: Close a variant iterator handle + +Input parameters: + +* `obj_handle` Object handle to be closed + +Output: None + +Exceptions that can be thrown by `amdsmi_dev_supported_func_iterator_close` function: +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: +```python +try: + devices = amdsmi_get_device_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + for device in devices: + obj_handle = amdsmi_dev_supported_func_iterator_open(device) + amdsmi_dev_supported_func_iterator_close(obj_handle) +except AmdSmiException as e: + print(e) +``` + +## amdsmi_func_iter_value_get +Description: Get the value associated with a function/variant iterator + +Input parameters: + +* `obj_handle` Object handle to query + +Output: Data associated with a function/variant iterator + +Field | Description +---|--- +`id`| Internal ID of the function/variant +`name`| Descriptive name of the function/variant +`amd_id_0` |
Subfield Description
`memory_type`Memory type
`temp_metric`Temperature metric
`evnt_type`Event type
`evnt_group`Event group
`clk_type`Clock type
`fw_block`Firmware block
`gpu_block_type`GPU block type
+ +Exceptions that can be thrown by `amdsmi_func_iter_value_get` function: +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: +```python +try: + devices = amdsmi_get_device_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + for device in devices: + obj_handle = amdsmi_dev_supported_func_iterator_open(device) + value = amdsmi_func_iter_value_get(obj_handle) + print(value) + amdsmi_dev_supported_func_iterator_close(obj_handle) +except AmdSmiException as e: + print(e) +``` + +## amdsmi_dev_pci_bandwidth_set +Description: Control the set of allowed PCIe bandwidths that can be used + +Input parameters: +* `device_handle` handle for the given device +* `bw_bitmask` A bitmask indicating the indices of the bandwidths that are +to be enabled (1) and disabled (0) + +Output: None + +Exceptions that can be thrown by `amdsmi_dev_pci_bandwidth_set` function: +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: +```python +try: + devices = amdsmi_get_device_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + for device in devices: + amdsmi_dev_pci_bandwidth_set(device, 0) +except AmdSmiException as e: + print(e) +``` +## amdsmi_dev_power_cap_set +Description: Set the power cap value + +Input parameters: +* `device_handle` handle for the given device +* `sensor_ind` a 0-based sensor index. Normally, this will be 0. If a +device has more than one sensor, it could be greater than 0 +* `cap` int that indicates the desired power cap, in microwatts + +Output: None + +Exceptions that can be thrown by `amdsmi_dev_power_cap_set` function: +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: +```python +try: + devices = amdsmi_get_device_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + for device in devices: + power_cap = 250 * 1000000 + amdsmi_dev_power_cap_set(device, 0, power_cap) +except AmdSmiException as e: + print(e) +``` +## amdsmi_dev_power_profile_set +Description: Set the power profile + +Input parameters: +* `device_handle` handle for the given device +* `reserved` Not currently used, set to 0 +* `profile` a amdsmi_power_profile_preset_masks_t that hold the mask of +the desired new power profile + +Output: None + +Exceptions that can be thrown by `amdsmi_dev_power_profile_set` function: +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: +```python +try: + devices = amdsmi_get_device_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + for device in devices: + profile = ... + amdsmi_dev_power_profile_set(device, 0, profile) +except AmdSmiException as e: + print(e) +``` +## amdsmi_dev_clk_range_set +Description: This function sets the clock range information + +Input parameters: +* `device_handle` handle for the given device +* `min_clk_value` minimum clock value for desired clock range +* `max_clk_value` maximum clock value for desired clock range +* `clk_type`AMDSMI_CLK_TYPE_SYS | AMDSMI_CLK_TYPE_MEM range type + +Output: None + +Exceptions that can be thrown by `amdsmi_dev_clk_range_set` function: +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: +```python +try: + devices = amdsmi_get_device_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + for device in devices: + amdsmi_dev_clk_range_set(device, 0, 1000, AmdSmiClockType.AMDSMI_CLK_TYPE_SYS) +except AmdSmiException as e: + print(e) +``` +## amdsmi_dev_od_clk_info_set +Description: This function sets the clock frequency information + +Input parameters: +* `device_handle` handle for the given device +* `level` AMDSMI_FREQ_IND_MIN|AMDSMI_FREQ_IND_MAX to set the minimum (0) +or maximum (1) speed +* `clk_value` value to apply to the clock range +* `clk_type` AMDSMI_CLK_TYPE_SYS | AMDSMI_CLK_TYPE_MEM range type + +Output: None + +Exceptions that can be thrown by `amdsmi_dev_od_clk_info_set` function: +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: +```python +try: + devices = amdsmi_get_device_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + for device in devices: + amdsmi_dev_od_clk_info_set( + device, + AmdSmiFreqInd.AMDSMI_FREQ_IND_MAX, + 1000, + AmdSmiClockType.AMDSMI_CLK_TYPE_SYS + ) +except AmdSmiException as e: + print(e) +``` +## amdsmi_dev_od_volt_info_set +Description: This function sets 1 of the 3 voltage curve points + +Input parameters: +* `device_handle` handle for the given device +* `vpoint` voltage point [0|1|2] on the voltage curve +* `clk_value` clock value component of voltage curve point +* `volt_value` voltage value component of voltage curve point + +Output: None + +Exceptions that can be thrown by `amdsmi_dev_od_volt_info_set` function: +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: +```python +try: + devices = amdsmi_get_device_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + for device in devices: + amdsmi_dev_od_volt_info_set(device, 1, 1000, 980) +except AmdSmiException as e: + print(e) +``` +## amdsmi_dev_perf_level_set_v1 +Description: Set the PowerPlay performance level associated with the device +with provided device handle with the provided value + +Input parameters: +* `device_handle` handle for the given device +* `perf_lvl` the value to which the performance level should be set + +Output: None + +Exceptions that can be thrown by `amdsmi_dev_perf_level_set_v1` function: +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: +```python +try: + devices = amdsmi_get_device_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + for device in devices: + amdsmi_dev_perf_level_set_v1(device, AmdSmiDevPerfLevel.AMDSMI_DEV_PERF_LEVEL_HIGH) +except AmdSmiException as e: + print(e) +``` \ No newline at end of file diff --git a/projects/amdsmi/py-interface/__init__.py b/projects/amdsmi/py-interface/__init__.py index 81ed597e7e..4a2c7855a2 100644 --- a/projects/amdsmi/py-interface/__init__.py +++ b/projects/amdsmi/py-interface/__init__.py @@ -71,6 +71,23 @@ from .amdsmi_interface import amdsmi_get_board_info # # Ras Information from .amdsmi_interface import amdsmi_get_ras_block_features_enabled +# # Supported Function Checks +from .amdsmi_interface import amdsmi_dev_supported_func_iterator_open +from .amdsmi_interface import amdsmi_dev_supported_variant_iterator_open +from .amdsmi_interface import amdsmi_dev_supported_func_iterator_close +from .amdsmi_interface import amdsmi_func_iter_next +from .amdsmi_interface import amdsmi_func_iter_value_get + +# # Unsupported Functions In Virtual Environment +from .amdsmi_interface import amdsmi_dev_pci_bandwidth_set +from .amdsmi_interface import amdsmi_dev_power_cap_set +from .amdsmi_interface import amdsmi_dev_power_profile_set +from .amdsmi_interface import amdsmi_dev_clk_range_set +from .amdsmi_interface import amdsmi_dev_od_clk_info_set +from .amdsmi_interface import amdsmi_dev_od_volt_info_set +from .amdsmi_interface import amdsmi_dev_perf_level_set_v1 + + # # Events # from .smi_interface import EventListen diff --git a/projects/amdsmi/py-interface/amdsmi_interface.py b/projects/amdsmi/py-interface/amdsmi_interface.py index ab09fb8ce3..90c930a24c 100644 --- a/projects/amdsmi/py-interface/amdsmi_interface.py +++ b/projects/amdsmi/py-interface/amdsmi_interface.py @@ -405,9 +405,7 @@ def _amdsmi_get_socket_handles() -> List[amdsmi_wrapper.amdsmi_socket_handle]: socket_count = ctypes.c_uint32(0) null_ptr = ctypes.POINTER(amdsmi_wrapper.amdsmi_socket_handle)() _check_res( - amdsmi_wrapper.amdsmi_get_socket_handles( - ctypes.byref(socket_count), null_ptr - ) + amdsmi_wrapper.amdsmi_get_socket_handles(ctypes.byref(socket_count), null_ptr) ) socket_handles = (amdsmi_wrapper.amdsmi_socket_handle * socket_count.value)() _check_res( @@ -1026,3 +1024,259 @@ def amdsmi_get_device_handle_from_bdf( ) return device_handle + + +def amdsmi_dev_supported_func_iterator_open( + device_handle: amdsmi_wrapper.amdsmi_device_handle, +) -> amdsmi_wrapper.amdsmi_func_id_iter_handle_t: + if not isinstance(device_handle, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle, amdsmi_wrapper.amdsmi_device_handle + ) + + obj_handle = amdsmi_wrapper.amdsmi_func_id_iter_handle_t() + _check_res( + amdsmi_wrapper.amdsmi_dev_supported_func_iterator_open( + device_handle, ctypes.byref(obj_handle) + ) + ) + + return obj_handle + + +def amdsmi_dev_supported_variant_iterator_open( + obj_handle: amdsmi_wrapper.amdsmi_func_id_iter_handle_t, +) -> amdsmi_wrapper.amdsmi_func_id_iter_handle_t: + if not isinstance(obj_handle, amdsmi_wrapper.amdsmi_func_id_iter_handle_t): + raise AmdSmiParameterException( + obj_handle, amdsmi_wrapper.amdsmi_func_id_iter_handle_t + ) + + var_iter = amdsmi_wrapper.amdsmi_func_id_iter_handle_t() + _check_res( + amdsmi_wrapper.amdsmi_dev_supported_variant_iterator_open( + obj_handle, ctypes.byref(var_iter) + ) + ) + + return var_iter + + +def amdsmi_dev_supported_func_iterator_close( + obj_handle: amdsmi_wrapper.amdsmi_func_id_iter_handle_t, +) -> None: + if not isinstance(obj_handle, amdsmi_wrapper.amdsmi_func_id_iter_handle_t): + raise AmdSmiParameterException( + obj_handle, amdsmi_wrapper.amdsmi_func_id_iter_handle_t + ) + + _check_res( + amdsmi_wrapper.amdsmi_dev_supported_func_iterator_close( + obj_handle, ctypes.byref(obj_handle) + ) + ) + + +def amdsmi_func_iter_next( + obj_handle: amdsmi_wrapper.amdsmi_func_id_iter_handle_t, +) -> amdsmi_wrapper.amdsmi_func_id_iter_handle_t: + if not isinstance(obj_handle, amdsmi_wrapper.amdsmi_func_id_iter_handle_t): + raise AmdSmiParameterException( + obj_handle, amdsmi_wrapper.amdsmi_func_id_iter_handle_t + ) + + _check_res(amdsmi_wrapper.amdsmi_func_iter_next(obj_handle)) + + return obj_handle + + +def amdsmi_func_iter_value_get( + obj_handle: amdsmi_wrapper.amdsmi_func_id_iter_handle_t, +) -> amdsmi_wrapper.amdsmi_func_id_value_t: + if not isinstance(obj_handle, amdsmi_wrapper.amdsmi_func_id_iter_handle_t): + raise AmdSmiParameterException( + obj_handle, amdsmi_wrapper.amdsmi_func_id_iter_handle_t + ) + + value = amdsmi_wrapper.amdsmi_func_id_value_t() + _check_res( + amdsmi_wrapper.amdsmi_func_iter_value_get(obj_handle, ctypes.byref(value)) + ) + + return { + "id": value.id, + "name": amdsmi_wrapper.string_cast(value.name), + "amd_id_0": { + "memory_type": value.amd_id_0.memory_type, + "temp_metric": value.amd_id_0.temp_metric, + "evnt_type": value.amd_id_0.evnt_type, + "evnt_group": value.amd_id_0.evnt_group, + "clk_type": value.amd_id_0.clk_type, + "fw_block": value.amd_id_0.fw_block, + "gpu_block_type": value.amd_id_0.gpu_block_type, + }, + } + + +def amdsmi_dev_pci_bandwidth_set( + device_handle: amdsmi_wrapper.amdsmi_device_handle, bitmask: int +) -> None: + if not isinstance(device_handle, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle, amdsmi_wrapper.amdsmi_device_handle + ) + + if not isinstance(bitmask, int): + raise AmdSmiParameterException(bitmask, int) + + _check_res( + amdsmi_wrapper.amdsmi_dev_pci_bandwidth_set( + device_handle, ctypes.c_uint64(bitmask) + ) + ) + + +def amdsmi_dev_power_cap_set( + device_handle: amdsmi_wrapper.amdsmi_device_handle, sensor_ind: int, cap: int +) -> None: + if not isinstance(device_handle, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle, amdsmi_wrapper.amdsmi_device_handle + ) + + if not isinstance(sensor_ind, int): + raise AmdSmiParameterException(sensor_ind, int) + + if not isinstance(cap, int): + raise AmdSmiParameterException(cap, int) + + _check_res( + amdsmi_wrapper.amdsmi_dev_power_cap_set( + device_handle, ctypes.c_uint32(sensor_ind), ctypes.c_uint64(cap) + ) + ) + + +def amdsmi_dev_power_profile_set( + device_handle: amdsmi_wrapper.amdsmi_device_handle, + reserved: int, + profile: AmdSmiPowerProfilePresetMasks, +) -> None: + if not isinstance(device_handle, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle, amdsmi_wrapper.amdsmi_device_handle + ) + + if not isinstance(reserved, int): + raise AmdSmiParameterException(reserved, int) + + if not isinstance(profile, AmdSmiPowerProfilePresetMasks): + raise AmdSmiParameterException(profile, AmdSmiPowerProfilePresetMasks) + + _check_res( + amdsmi_wrapper.amdsmi_dev_power_profile_set( + device_handle, ctypes.c_uint32(reserved), profile + ) + ) + + +def amdsmi_dev_clk_range_set( + device_handle: amdsmi_wrapper.amdsmi_device_handle, + min_clk_value: int, + max_clk_value: int, + clk_type: AmdSmiClockType, +) -> None: + if not isinstance(device_handle, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle, amdsmi_wrapper.amdsmi_device_handle + ) + + if not isinstance(min_clk_value, int): + raise AmdSmiParameterException(min_clk_value, int) + + if not isinstance(max_clk_value, int): + raise AmdSmiParameterException(min_clk_value, int) + + if not isinstance(clk_type, AmdSmiClockType): + raise AmdSmiParameterException(clk_type, AmdSmiClockType) + + _check_res( + amdsmi_wrapper.amdsmi_dev_clk_range_set( + device_handle, + ctypes.c_uint64(min_clk_value), + ctypes.c_uint64(max_clk_value), + clk_type, + ) + ) + + +def amdsmi_dev_od_clk_info_set( + device_handle: amdsmi_wrapper.amdsmi_device_handle, + level: AmdSmiFreqInd, + value: int, + clk_type: AmdSmiClockType, +) -> None: + if not isinstance(device_handle, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle, amdsmi_wrapper.amdsmi_device_handle + ) + + if not isinstance(level, AmdSmiFreqInd): + raise AmdSmiParameterException(level, AmdSmiFreqInd) + + if not isinstance(value, int): + raise AmdSmiParameterException(value, int) + + if not isinstance(clk_type, AmdSmiClockType): + raise AmdSmiParameterException(clk_type, AmdSmiClockType) + + _check_res( + amdsmi_wrapper.amdsmi_dev_od_clk_info_set( + device_handle, level, ctypes.c_uint64(value), clk_type + ) + ) + + +def amdsmi_dev_od_volt_info_set( + device_handle: amdsmi_wrapper.amdsmi_device_handle, + vpoint: int, + clk_value: int, + volt_value: int, +) -> None: + if not isinstance(device_handle, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle, amdsmi_wrapper.amdsmi_device_handle + ) + + if not isinstance(vpoint, int): + raise AmdSmiParameterException(vpoint, int) + + if not isinstance(clk_value, int): + raise AmdSmiParameterException(clk_value, int) + + if not isinstance(volt_value, int): + raise AmdSmiParameterException(volt_value, int) + + _check_res( + amdsmi_wrapper.amdsmi_dev_od_volt_info_set( + device_handle, + ctypes.c_uint32(vpoint), + ctypes.c_uint64(clk_value), + ctypes.c_uint64(volt_value), + ) + ) + + +def amdsmi_dev_perf_level_set_v1( + device_handle: amdsmi_wrapper.amdsmi_device_handle, + perf_lvl: AmdSmiDevPerfLevel, +) -> None: + if not isinstance(device_handle, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle, amdsmi_wrapper.amdsmi_device_handle + ) + + if not isinstance(perf_lvl, AmdSmiDevPerfLevel): + raise AmdSmiParameterException(perf_lvl, AmdSmiDevPerfLevel) + + _check_res(amdsmi_wrapper.amdsmi_dev_perf_level_set_v1(device_handle, perf_lvl))