SWDEV-361376 - Add events to python interface
- Implement context manager event class for easier usage instead of having 4 different
APIs.
- Add support for with statement for easier cleanup.
Change-Id: I396947a93d3f04efc068e17804eab12eefa97cf0
Signed-off-by: Dalibor Stanisavljevic <Dalibor.Stanisavljevic@amd.com>
[ROCm/amdsmi commit: 23160fa8e0]
Этот коммит содержится в:
@@ -1089,50 +1089,73 @@ except SmiException as e:
|
||||
print(e)
|
||||
```
|
||||
|
||||
## EventListen class
|
||||
## AmdSmiEventReader class
|
||||
|
||||
Description: Providing methods for event monitoring
|
||||
Description: Providing methods for event monitoring. This is context manager class.
|
||||
Can be used with `with` statement for automatic cleanup.
|
||||
|
||||
Methods:
|
||||
|
||||
## Constructor
|
||||
|
||||
Description: Allocates a new event reader notifier to monitor different types of events with the multiple GPUs
|
||||
Description: Allocates a new event reader notifier to monitor different types of events for the given GPU
|
||||
|
||||
Input parameters:
|
||||
|
||||
* `event_types` types of events to monitor and react on
|
||||
* `device_handle` device handle corresponding to the device on which to listen for events
|
||||
* `event_types` list of event types from AmdSmiEvtNotificationType enum. Specifying which events to collect for the given device.
|
||||
|
||||
Event Type | Description
|
||||
---|------
|
||||
`VMFAULT` | VM page fault
|
||||
`THERMAL_THROTTLE` | thermal throttle
|
||||
`GPU_PRE_RESET` | gpu pre reset
|
||||
`GPU_POST_RESET` | gpu post reset
|
||||
|
||||
## read
|
||||
|
||||
Description: Reads events on GPUs. When event is caught, device handle, event id, message, event type and
|
||||
time are returned. Reading events stops when timestamp passes without event reading.
|
||||
Description: Reads events on the given device. When event is caught, device handle, message and event type are returned. Reading events stops when timestamp passes without event reading.
|
||||
|
||||
Input parameters:
|
||||
|
||||
* `timestamp` Amount of miliseconds to wait for event. If event does not happen monitoring is finished
|
||||
* `i` GPU index to which we need to listen to events. For example 0,1,2...
|
||||
* `timestamp` number of milliseconds to wait for an event to occur. If event does not happen monitoring is finished
|
||||
* `num_elem` number of events. This is optional parameter. Default value is 10.
|
||||
|
||||
Example:
|
||||
```python
|
||||
try:
|
||||
devices = gpuvsmi_get_devices()
|
||||
if len(devices) == 0:
|
||||
print("No GPUs on machine")
|
||||
else:
|
||||
device = devices[0]
|
||||
listener = EventListen(SmiEventType.GPU_PRE_RESET)
|
||||
listener.read(10000)
|
||||
except SmiException as e:
|
||||
print(e)
|
||||
```
|
||||
## stop
|
||||
|
||||
## Destructor
|
||||
|
||||
Description: Detroys event listener object, closes all open files and directories
|
||||
Description: Any resources used by event notification for the the given device will be freed with this function. This can be used explicitly or
|
||||
automatically using `with` statement, like in the examples below. This should be called either manually or automatically for every created AmdSmiEventReader object.
|
||||
|
||||
Input parameters: `None`
|
||||
|
||||
Example with manual cleanup of AmdSmiEventReader:
|
||||
```python
|
||||
try:
|
||||
devices = amdsmi_get_device_handles()
|
||||
if len(devices) == 0:
|
||||
print("No GPUs on machine")
|
||||
else:
|
||||
event = AmdSmiEventReader(device[0], AmdSmiEvtNotificationType.GPU_PRE_RESET, AmdSmiEvtNotificationType.GPU_POST_RESET)
|
||||
event.read(10000)
|
||||
except AmdSmiException as e:
|
||||
print(e)
|
||||
finally:
|
||||
event.stop()
|
||||
```
|
||||
|
||||
Example with automatic cleanup using `with` statement:
|
||||
```python
|
||||
try:
|
||||
devices = amdsmi_get_device_handles()
|
||||
if len(devices) == 0:
|
||||
print("No GPUs on machine")
|
||||
else:
|
||||
with AmdSmiEventReader(device[0], AmdSmiEvtNotificationType.GPU_PRE_RESET, AmdSmiEvtNotificationType.GPU_POST_RESET) as event:
|
||||
event.read(10000)
|
||||
except AmdSmiException as e:
|
||||
print(e)
|
||||
|
||||
```
|
||||
|
||||
## amdsmi_dev_supported_func_iterator_open
|
||||
Description: Get a function name iterator of supported AMDSMI functions for a device
|
||||
|
||||
@@ -89,7 +89,7 @@ from .amdsmi_interface import amdsmi_dev_perf_level_set_v1
|
||||
|
||||
|
||||
# # Events
|
||||
# from .smi_interface import EventListen
|
||||
from .amdsmi_interface import AmdSmiEventReader
|
||||
|
||||
# # Enums
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
import ctypes
|
||||
from typing import Union, Any, Dict, List, Tuple
|
||||
from enum import IntEnum
|
||||
|
||||
from collections.abc import Iterable
|
||||
|
||||
from . import amdsmi_wrapper
|
||||
from .amdsmi_exception import *
|
||||
@@ -291,6 +291,57 @@ class AmdSmiUtilizationCounterType(IntEnum):
|
||||
COARSE_GRAIN_MEM_ACTIVITY = amdsmi_wrapper.AMDSMI_COARSE_GRAIN_MEM_ACTIVITY
|
||||
|
||||
|
||||
class AmdSmiEventReader:
|
||||
def __init__(self, device_handle: amdsmi_wrapper.amdsmi_device_handle, *event_types):
|
||||
if not isinstance(device_handle, amdsmi_wrapper.amdsmi_device_handle):
|
||||
raise AmdSmiParameterException(
|
||||
device_handle, amdsmi_wrapper.amdsmi_device_handle
|
||||
)
|
||||
if not isinstance(event_types, Iterable):
|
||||
raise AmdSmiParameterException(
|
||||
event_types, Iterable
|
||||
)
|
||||
|
||||
for event_type in event_types:
|
||||
if not isinstance(event_type, AmdSmiEvtNotificationType):
|
||||
raise AmdSmiParameterException(
|
||||
event_type, AmdSmiEvtNotificationType
|
||||
)
|
||||
|
||||
self.device_handle = device_handle
|
||||
mask = 0
|
||||
for event_type in event_types:
|
||||
mask |= (1 << (int(event_type) - 1))
|
||||
|
||||
_check_res(amdsmi_wrapper.amdsmi_event_notification_init(device_handle))
|
||||
_check_res(amdsmi_wrapper.amdsmi_event_notification_mask_set(device_handle, ctypes.c_uint64(mask)))
|
||||
|
||||
def read(self, timestamp, num_elem = 10):
|
||||
self.event_info = (amdsmi_wrapper.amdsmi_evt_notification_data_t * num_elem)()
|
||||
_check_res(amdsmi_wrapper.amdsmi_event_notification_get(ctypes.c_int(timestamp), ctypes.byref(
|
||||
ctypes.c_uint32(num_elem)), self.event_info))
|
||||
|
||||
ret = list()
|
||||
for i in range(0, num_elem):
|
||||
if self.event_info[i].event in set(event.value for event in AmdSmiEvtNotificationType):
|
||||
ret.append({
|
||||
'device_handle' : self.event_info[i].device_handle,
|
||||
'event': AmdSmiEvtNotificationType(self.event_info[i].event).name,
|
||||
'message': self.event_info[i].message.decode("utf-8")
|
||||
})
|
||||
|
||||
return ret
|
||||
|
||||
def stop(self):
|
||||
_check_res(amdsmi_wrapper.amdsmi_event_notification_stop(self.device_handle))
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
self.stop()
|
||||
|
||||
|
||||
_AMDSMI_MAX_DRIVER_VERSION_LENGTH = 80
|
||||
_AMDSMI_GPU_UUID_SIZE = 38
|
||||
|
||||
|
||||
Ссылка в новой задаче
Block a user