From 50133d44c271229f704c5a9955de1bde539e8ab2 Mon Sep 17 00:00:00 2001 From: Dalibor Stanisavljevic Date: Thu, 10 Nov 2022 15:29:32 +0100 Subject: [PATCH] SWDEV-361376 - Updated python API Signed-off-by: Dalibor Stanisavljevic Change-Id: I8d81154b27111b849dbb645e024ebf322299f851 --- py-interface/README.md | 426 +++++++++++++++++++++++++++++++ py-interface/__init__.py | 23 +- py-interface/amdsmi_interface.py | 280 ++++++++++++++++++++ 3 files changed, 728 insertions(+), 1 deletion(-) diff --git a/py-interface/README.md b/py-interface/README.md index 6159d8ae54..f5fd8de096 100644 --- a/py-interface/README.md +++ b/py-interface/README.md @@ -2634,3 +2634,429 @@ try: except AmdSmiException as e: print(e) ``` +## amdsmi_dev_vendor_name_get +Description: Returns the device vendor name + +Input parameters: + +* `device_handle` device which to query + +Output: device vendor name + +Exceptions that can be thrown by `amdsmi_dev_vendor_name_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: + vendor_name = amdsmi_dev_vendor_name_get(device) + print(vendor_name) +except AmdSmiException as e: + print(e) +``` + +## amdsmi_dev_id_get +Description: Get the device id associated with the device with provided device handler + +Input parameters: + +* `device_handle` device which to query + +Output: device id + +Exceptions that can be thrown by `amdsmi_dev_id_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: + dev_id = amdsmi_dev_id_get(device) + print(dev_id) +except AmdSmiException as e: + print(e) +``` + +## amdsmi_dev_vram_vendor_get +Description: Get the vram vendor string of a gpu device. + +Input parameters: + +* `device_handle` device which to query + +Output: vram vendor + +Exceptions that can be thrown by `amdsmi_dev_vram_vendor_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: + vram_vendor = amdsmi_dev_vram_vendor_get(device) + print(vram_vendor) +except AmdSmiException as e: + print(e) +``` + +## amdsmi_dev_drm_render_minor_get +Description: Get the drm minor number associated with this device. + +Input parameters: + +* `device_handle` device which to query + +Output: drm minor number + +Exceptions that can be thrown by `amdsmi_dev_drm_render_minor_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: + render_minor = amdsmi_dev_drm_render_minor_get(device) + print(render_minor) +except AmdSmiException as e: + print(e) +``` + +## amdsmi_dev_subsystem_id_get +Description: Get the subsystem device id associated with the device with provided device handle. + +Input parameters: + +* `device_handle` device which to query + +Output: subsystem device id + +Exceptions that can be thrown by `amdsmi_dev_subsystem_id_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: + id = amdsmi_dev_subsystem_id_get(device) + print(id) +except AmdSmiException as e: + print(e) +``` + + +## amdsmi_dev_subsystem_name_get +Description: Get the name string for the device subsytem + +Input parameters: + +* `device_handle` device which to query + +Output: device subsytem + +Exceptions that can be thrown by `amdsmi_dev_subsystem_name_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: + subsystem_nam = amdsmi_dev_subsystem_name_get(device) + print(subsystem_nam) +except AmdSmiException as e: + print(e) +``` + + +## amdsmi_version_get +Description: Get the build version information for the currently running build of AMDSMI. + +Output: amdsmi build version + +Exceptions that can be thrown by `amdsmi_version_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: + version = amdsmi_version_get() + print(version) +except AmdSmiException as e: + print(e) +``` + + +## amdsmi_version_str_get +Description: Get the driver version string for the current system. + +Input parameters: + +* `sw_component` software component which to query + +Output: driver version string + +Exceptions that can be thrown by `amdsmi_version_str_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: + version = amdsmi_version_str_get(AmdSmiSwComponent.DRIVER) + print(version) +except AmdSmiException as e: + print(e) +``` + + +## amdsmi_topo_get_numa_node_number +Description: Retrieve the NUMA CPU node number for a device + +Input parameters: + +* `device_handle` device which to query + +Output: node number of NUMA CPU for the device + +Exceptions that can be thrown by `amdsmi_topo_get_numa_node_number` 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: + node_number = amdsmi_topo_get_numa_node_number() + print(node_number) +except AmdSmiException as e: + print(e) +``` + +## amdsmi_topo_get_link_weight +Description: Retrieve the weight for a connection between 2 GPUs. + +Input parameters: + +* `device_handle_src` the source device handle +* `device_handle_dest` the destination device handle + +Output: the weight for a connection between 2 GPUs + +Exceptions that can be thrown by `amdsmi_topo_get_link_weight` function: +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: +```python +try: + devices = amdsmi_get_device_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + device_handle_src = devices[0] + device_handle_dest = devices[1] + weight = amdsmi_topo_get_link_weight(device_handle_src, device_handle_dest) + print(weight) +except AmdSmiException as e: + print(e) +``` + + +## amdsmi_minmax_bandwidth_get +Description: Retreive minimal and maximal io link bandwidth between 2 GPUs. + +Input parameters: + +* `device_handle_src` the source device handle +* `device_handle_dest` the destination device handle + +Output: Dictionary with fields: + +Field | Description +---|--- +`min_bandwidth` | minimal bandwidth for the connection +`max_bandwidth` | maximal bandwidth for the connection + +Exceptions that can be thrown by `amdsmi_minmax_bandwidth_get` function: +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: +```python +try: + devices = amdsmi_get_device_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + device_handle_src = devices[0] + device_handle_dest = devices[1] + bandwith = amdsmi_minmax_bandwidth_get(device_handle_src, device_handle_dest) + print(bandwith['min_bandwidth']) + print(bandwith['max_bandwidth']) +except AmdSmiException as e: + print(e) +``` + + +## amdsmi_topo_get_link_type +Description: Retrieve the hops and the connection type between 2 GPUs + +Input parameters: + +* `device_handle_src` the source device handle +* `device_handle_dest` the destination device handle + +Output: Dictionary with fields: + +Field | Description +---|--- +`hops` | number of hops +`type` | the connection type + +Exceptions that can be thrown by `amdsmi_topo_get_link_type` function: +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: +```python +try: + devices = amdsmi_get_device_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + device_handle_src = devices[0] + device_handle_dest = devices[1] + link_type = amdsmi_topo_get_link_type(device_handle_src, device_handle_dest) + print(link_type['hops']) + print(link_type['type']) +except AmdSmiException as e: + print(e) +``` + + +## amdsmi_is_P2P_accessible +Description: Return P2P availability status between 2 GPUs + +Input parameters: + +* `device_handle_src` the source device handle +* `device_handle_dest` the destination device handle + +Output: P2P availability status between 2 GPUs + +Exceptions that can be thrown by `amdsmi_is_P2P_accessible` function: +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: +```python +try: + devices = amdsmi_get_device_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + device_handle_src = devices[0] + device_handle_dest = devices[1] + accessible = amdsmi_is_P2P_accessible(device_handle_src, device_handle_dest) + print(accessible) +except AmdSmiException as e: + print(e) +``` + + +## amdsmi_get_xgmi_info +Description: Returns XGMI information for the GPU. + +Input parameters: + +* `device_handle` device handle + +Output: Dictionary with fields: + +Field | Description +---|--- +`xgmi_lanes` | xgmi lanes +`xgmi_hive_id` | xgmi hive id +`xgmi_node_id` | xgmi node id +`index` | index + + +Exceptions that can be thrown by `amdsmi_get_xgmi_info` 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: + xgmi_info = amdsmi_get_xgmi_info(device) + print(xgmi_info['xgmi_lanes']) + print(xgmi_info['xgmi_hive_id']) + print(xgmi_info['xgmi_node_id']) + print(xgmi_info['index']) +except AmdSmiException as e: + print(e) +``` diff --git a/py-interface/__init__.py b/py-interface/__init__.py index 4d2fd12a71..5b61f15053 100644 --- a/py-interface/__init__.py +++ b/py-interface/__init__.py @@ -139,6 +139,26 @@ from .amdsmi_interface import amdsmi_dev_xgmi_error_reset # # Events from .amdsmi_interface import AmdSmiEventReader +# # Device Identification information +from .amdsmi_interface import amdsmi_dev_vendor_name_get +from .amdsmi_interface import amdsmi_dev_id_get +from .amdsmi_interface import amdsmi_dev_vram_vendor_get +from .amdsmi_interface import amdsmi_dev_drm_render_minor_get +from .amdsmi_interface import amdsmi_dev_subsystem_id_get +from .amdsmi_interface import amdsmi_dev_subsystem_name_get + +# # Version information +from .amdsmi_interface import amdsmi_version_get +from .amdsmi_interface import amdsmi_version_str_get + +# # Hardware topology query +from .amdsmi_interface import amdsmi_topo_get_numa_node_number +from .amdsmi_interface import amdsmi_topo_get_link_weight +from .amdsmi_interface import amdsmi_minmax_bandwidth_get +from .amdsmi_interface import amdsmi_topo_get_link_type +from .amdsmi_interface import amdsmi_is_P2P_accessible +from .amdsmi_interface import amdsmi_get_xgmi_info + # # Enums from .amdsmi_interface import AmdSmiInitFlags @@ -166,7 +186,8 @@ from .amdsmi_interface import AmdSmiXgmiStatus from .amdsmi_interface import AmdSmiMemoryPageStatus from .amdsmi_interface import AmdSmiIoLinkType from .amdsmi_interface import AmdSmiUtilizationCounterType - +from .amdsmi_interface import AmdSmiSwComponent +from .amdsmi_interface import AmdSmiIoLinkType # Exceptions from .amdsmi_exception import AmdSmiLibraryException diff --git a/py-interface/amdsmi_interface.py b/py-interface/amdsmi_interface.py index 88d73c8144..6e0374b05a 100644 --- a/py-interface/amdsmi_interface.py +++ b/py-interface/amdsmi_interface.py @@ -290,6 +290,18 @@ class AmdSmiUtilizationCounterType(IntEnum): COARSE_GRAIN_MEM_ACTIVITY = amdsmi_wrapper.AMDSMI_COARSE_GRAIN_MEM_ACTIVITY +class AmdSmiSwComponent(IntEnum): + DRIVER = amdsmi_wrapper.AMDSMI_SW_COMP_DRIVER + + +class AmdSmiIoLinkType(IntEnum): + UNDEFINED = amdsmi_wrapper.AMDSMI_IOLINK_TYPE_UNDEFINED + PCIEXPRESS = amdsmi_wrapper.AMDSMI_IOLINK_TYPE_PCIEXPRESS + XGMI = amdsmi_wrapper.AMDSMI_IOLINK_TYPE_XGMI + NUMIOLINKTYPES = amdsmi_wrapper.AMDSMI_IOLINK_TYPE_NUMIOLINKTYPES + SIZE = amdsmi_wrapper.AMDSMI_IOLINK_TYPE_SIZE + + class AmdSmiEventReader: def __init__( self, device_handle: amdsmi_wrapper.amdsmi_device_handle, *event_types @@ -356,6 +368,7 @@ class AmdSmiEventReader: _AMDSMI_MAX_DRIVER_VERSION_LENGTH = 80 _AMDSMI_GPU_UUID_SIZE = 38 +_AMDSMI_STRING_LENGTH = 80 def _parse_fw_info(fw_info: amdsmi_wrapper.amdsmi_fw_info_t) -> Dict[str, Any]: @@ -1099,6 +1112,273 @@ def amdsmi_get_device_handle_from_bdf( return device_handle +def amdsmi_dev_vendor_name_get( + device_handle: amdsmi_wrapper.amdsmi_device_handle, +) -> str: + if not isinstance(device_handle, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle, amdsmi_wrapper.amdsmi_device_handle + ) + + length = ctypes.c_uint64() + length.value = _AMDSMI_STRING_LENGTH + + vendor_name = ctypes.create_string_buffer(_AMDSMI_STRING_LENGTH) + + _check_res( + amdsmi_wrapper.amdsmi_dev_vendor_name_get(device_handle, vendor_name, length) + ) + + return vendor_name.value.decode("utf-8") + + +def amdsmi_dev_id_get(device_handle: amdsmi_wrapper.amdsmi_device_handle): + if not isinstance(device_handle, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle, amdsmi_wrapper.amdsmi_device_handle + ) + id = ctypes.c_uint16() + + _check_res(amdsmi_wrapper.amdsmi_dev_id_get(device_handle, ctypes.byref(id))) + + return id.value + + +def amdsmi_dev_vram_vendor_get(device_handle: amdsmi_wrapper.amdsmi_device_handle): + if not isinstance(device_handle, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle, amdsmi_wrapper.amdsmi_device_handle + ) + + length = ctypes.c_uint32() + length.value = _AMDSMI_STRING_LENGTH + + vram_vendor = ctypes.create_string_buffer(_AMDSMI_STRING_LENGTH) + + _check_res( + amdsmi_wrapper.amdsmi_dev_vram_vendor_get(device_handle, vram_vendor, length) + ) + + return vram_vendor.value.decode("utf-8") + + +def amdsmi_dev_drm_render_minor_get(device_handle: amdsmi_wrapper.amdsmi_device_handle): + if not isinstance(device_handle, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle, amdsmi_wrapper.amdsmi_device_handle + ) + minor = ctypes.c_uint32() + + _check_res( + amdsmi_wrapper.amdsmi_dev_drm_render_minor_get( + device_handle, ctypes.byref(minor) + ) + ) + + return minor.value + + +def amdsmi_dev_subsystem_id_get(device_handle: amdsmi_wrapper.amdsmi_device_handle): + if not isinstance(device_handle, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle, amdsmi_wrapper.amdsmi_device_handle + ) + id = ctypes.c_uint16() + + _check_res( + amdsmi_wrapper.amdsmi_dev_subsystem_id_get(device_handle, ctypes.byref(id)) + ) + + return id.value + + +def amdsmi_dev_subsystem_name_get(device_handle: amdsmi_wrapper.amdsmi_device_handle): + if not isinstance(device_handle, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle, amdsmi_wrapper.amdsmi_device_handle + ) + + length = ctypes.c_uint64() + length.value = _AMDSMI_STRING_LENGTH + + name = ctypes.create_string_buffer(_AMDSMI_STRING_LENGTH) + + _check_res( + amdsmi_wrapper.amdsmi_dev_subsystem_name_get(device_handle, name, length) + ) + + return name.value.decode("utf-8") + + +def amdsmi_version_get(): + version = amdsmi_wrapper.amdsmi_version_t() + + _check_res(amdsmi_wrapper.amdsmi_version_get(ctypes.byref(version))) + + return { + "major": version.major, + "minor": version.minor, + "patch": version.patch, + "build": version.build.contents.value.decode("utf-8"), + } + + +def amdsmi_version_str_get(sw_component: AmdSmiSwComponent): + if not isinstance(sw_component, AmdSmiSwComponent): + raise AmdSmiParameterException(sw_component, AmdSmiSwComponent) + + length = ctypes.c_uint32() + length.value = _AMDSMI_STRING_LENGTH + + ver_str = ctypes.create_string_buffer(_AMDSMI_STRING_LENGTH) + + _check_res(amdsmi_wrapper.amdsmi_version_str_get(sw_component, ver_str, length)) + + return ver_str.value.decode("utf-8") + + +def amdsmi_topo_get_numa_node_number( + device_handle: amdsmi_wrapper.amdsmi_device_handle, +): + if not isinstance(device_handle, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle, amdsmi_wrapper.amdsmi_device_handle + ) + + numa_node_number = ctypes.c_uint32() + + _check_res( + amdsmi_wrapper.amdsmi_topo_get_numa_node_number( + device_handle, ctypes.byref(numa_node_number) + ) + ) + + return numa_node_number.value + + +def amdsmi_topo_get_link_weight( + device_handle_src: amdsmi_wrapper.amdsmi_device_handle, + device_handle_dst: amdsmi_wrapper.amdsmi_device_handle, +): + if not isinstance(device_handle_src, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle_src, amdsmi_wrapper.amdsmi_device_handle + ) + + if not isinstance(device_handle_dst, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle_dst, amdsmi_wrapper.amdsmi_device_handle + ) + + weight = ctypes.c_uint64() + + _check_res( + amdsmi_wrapper.amdsmi_topo_get_link_weight( + device_handle_src, device_handle_dst, ctypes.byref(weight) + ) + ) + + return weight.value + + +def amdsmi_minmax_bandwidth_get( + device_handle_src: amdsmi_wrapper.amdsmi_device_handle, + device_handle_dst: amdsmi_wrapper.amdsmi_device_handle, +): + if not isinstance(device_handle_src, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle_src, amdsmi_wrapper.amdsmi_device_handle + ) + + if not isinstance(device_handle_dst, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle_dst, amdsmi_wrapper.amdsmi_device_handle + ) + + min_bandwidth = ctypes.c_uint64() + max_bandwidth = ctypes.c_uint64() + + _check_res( + amdsmi_wrapper.amdsmi_minmax_bandwidth_get( + device_handle_src, + device_handle_dst, + ctypes.byref(min_bandwidth), + ctypes.byref(max_bandwidth), + ) + ) + + return {"min_bandwidth": min_bandwidth.value, "max_bandwidth": max_bandwidth.value} + + +def amdsmi_topo_get_link_type( + device_handle_src: amdsmi_wrapper.amdsmi_device_handle, + device_handle_dst: amdsmi_wrapper.amdsmi_device_handle, +): + if not isinstance(device_handle_src, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle_src, amdsmi_wrapper.amdsmi_device_handle + ) + + if not isinstance(device_handle_dst, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle_dst, amdsmi_wrapper.amdsmi_device_handle + ) + + hops = ctypes.c_uint64() + type = AmdSmiIoLinkType() + + _check_res( + amdsmi_wrapper.amdsmi_topo_get_link_type( + device_handle_src, device_handle_dst, ctypes.byref(hops), type + ) + ) + + return {"hops": hops.value, "type": type} + + +def amdsmi_is_P2P_accessible( + device_handle_src: amdsmi_wrapper.amdsmi_device_handle, + device_handle_dst: amdsmi_wrapper.amdsmi_device_handle, +): + if not isinstance(device_handle_src, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle_src, amdsmi_wrapper.amdsmi_device_handle + ) + + if not isinstance(device_handle_dst, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle_dst, amdsmi_wrapper.amdsmi_device_handle + ) + + accessible = ctypes.c_bool() + + _check_res( + amdsmi_wrapper.amdsmi_is_P2P_accessible( + device_handle_src, device_handle_dst, ctypes.byref(accessible) + ) + ) + + return accessible.value + + +def amdsmi_get_xgmi_info(device_handle: amdsmi_wrapper.amdsmi_device_handle): + if not isinstance(device_handle, amdsmi_wrapper.amdsmi_device_handle): + raise AmdSmiParameterException( + device_handle, amdsmi_wrapper.amdsmi_device_handle + ) + + xgmi_info = amdsmi_wrapper.amdsmi_xgmi_info_t() + + _check_res(amdsmi_wrapper.amdsmi_get_xgmi_info(device_handle, xgmi_info)) + + return { + "xgmi_lanes": xgmi_info.xgmi_lanes, + "xgmi_hive_id": xgmi_info.xgmi_hive_id, + "xgmi_node_id": xgmi_info.xgmi_node_id, + "index": xgmi_info.index, + } + + def amdsmi_dev_counter_group_supported( device_handle: amdsmi_wrapper.amdsmi_device_handle, event_group: AmdSmiEventGroup,