from__future__importannotationsfromcollections.abcimportSequencefromtypingimportTYPE_CHECKING,Any,NamedTuplefrom._apiimportAPIfrom._platformimportPlatformfrom._utilsimportstring_matches_masksifTYPE_CHECKING:# pragma: no coverfrom._adapter_baseimportDeviceAdapter,DeviceParameters
[docs]classDeviceFilter(NamedTuple):"""A set of filters for device discovery."""include_masks:list[str]|None=None"""A list of strings (treated as regexes), one of which must match the device name."""exclude_masks:list[str]|None=None"""A list of strings (treated as regexes), neither of which must match the device name."""unique_only:bool=False"""If ``True``, only return devices with unique names."""exclude_pure_parallel:bool=False""" If ``True``, exclude devices with ``max_total_local_size`` equal to 1 (that is the ones that do not support workgroup synchronization). """
[docs]@classmethoddefall(cls,platform:Platform)->list[Device]:""" Returns a list of devices available for the given platform. :param platform: the platform to search in. """return[Device.from_index(platform,device_idx)fordevice_idxinrange(platform._platform_adapter.device_count)# noqa: SLF001]
[docs]@classmethoddefall_filtered(cls,platform:Platform,filter_:DeviceFilter|None=None,)->list[Device]:""" Returns a list of all devices satisfying the given criteria in the given platform. If ``filter`` is not provided, returns all the devices. """iffilter_isNone:returncls.all(platform)seen_devices=set()devices=[]fordeviceincls.all(platform):ifnotstring_matches_masks(device.name,include_masks=filter_.include_masks,exclude_masks=filter_.exclude_masks,):continueiffilter_.unique_onlyanddevice.nameinseen_devices:continueiffilter_.exclude_pure_parallelanddevice.params.max_total_local_size==1:continueseen_devices.add(device.name)devices.append(device)returndevices
[docs]@classmethoddeffrom_backend_device(cls,obj:Any)->Device:"""Wraps a backend device object into a Grunnur device object."""forapiinAPI.all_available():ifapi._api_adapter.isa_backend_device(obj):# noqa: SLF001device_adapter=api._api_adapter.make_device_adapter(obj)# noqa: SLF001returncls(device_adapter)raiseTypeError(f"{obj} was not recognized as a device object by any available API")
[docs]@classmethoddeffrom_index(cls,platform:Platform,device_idx:int)->Device:""" Creates a device based on its index in the list returned by the API. :param platform: the API to search in. :param device_idx: the target device's index. """device_adapter=platform._platform_adapter.get_device_adapters()[device_idx]# noqa: SLF001returncls(device_adapter)
def__init__(self,device_adapter:DeviceAdapter):self.platform=Platform(device_adapter.platform_adapter)self._device_adapter=device_adapterself.name=self._device_adapter.nameself.shortcut=f"{self.platform.shortcut},{device_adapter.device_idx}"self._params=Nonedef__eq__(self,other:object)->bool:returnisinstance(other,Device)andself._device_adapter==other._device_adapterdef__hash__(self)->int:returnhash((type(self),self._device_adapter))@propertydefparams(self)->DeviceParameters:""" Returns a :py:class:`~grunnur.DeviceParameters` object associated with this device. """# Already cached in the adaptersreturnself._device_adapter.paramsdef__str__(self)->str:returnf"device({self.shortcut})"