from__future__importannotationsfromtypingimportTYPE_CHECKING,Anyfrom._adapter_cudaimportCuAPIAdapterFactoryfrom._adapter_openclimportOclAPIAdapterFactoryifTYPE_CHECKING:# pragma: no coverfrom._adapter_baseimportAPIID,APIAdapterfrom._platformimportPlatformdefcuda_api_id()->APIID:"""Returns the identifier of CUDA API."""returnCuAPIAdapterFactory().api_iddefopencl_api_id()->APIID:"""Returns the identifier of OpenCL API."""returnOclAPIAdapterFactory().api_id_ALL_API_ADAPTER_FACTORIES={factory.api_id:factoryforfactoryin[CuAPIAdapterFactory(),OclAPIAdapterFactory(),]}defall_api_ids()->list[APIID]:""" Returns a list of identifiers for all APIs (not necessarily available in the current system). """returnlist(_ALL_API_ADAPTER_FACTORIES.keys())
[docs]classAPI:"""A generalized GPGPU API."""id:APIID"""This API's ID."""shortcut:str""" A shortcut for this API (to use in :py:meth:`all_by_shortcut`, usually coming from some kind of a CLI). Equal to ``id.shortcut``. """
[docs]@classmethoddefall_available(cls)->list[API]:""" Returns a list of :py:class:`~grunnur.API` objects for which backends are available. """return[cls.from_api_id(api_id)forapi_id,api_factoryin_ALL_API_ADAPTER_FACTORIES.items()ifapi_factory.available]
[docs]@classmethoddefall_by_shortcut(cls,shortcut:str|None=None)->list[API]:""" If ``shortcut`` is a string, returns a list of one :py:class:`~grunnur.API` object whose :py:attr:`~API.id` attribute has its :py:attr:`~grunnur._adapter_base.APIID.shortcut` attribute equal to it (or raises an error if it was not found, or its backend is not available). If ``shortcut`` is ``None``, returns a list of all available :py:class:`~grunnur.API` objects. :param shortcut: an API shortcut to match. """ifshortcutisNone:apis=cls.all_available()else:forapi_id,api_factoryin_ALL_API_ADAPTER_FACTORIES.items():ifshortcut==api_id.shortcut:ifnotapi_factory.available:raiseValueError(str(shortcut)+" API is not available")apis=[cls.from_api_id(api_id)]breakelse:raiseValueError("Invalid API shortcut: "+str(shortcut))returnapis
[docs]@classmethoddeffrom_api_id(cls,api_id:APIID)->API:""" Creates an :py:class:`~grunnur.API` object out of an identifier. :param api_id: API identifier. """api_adapter=_ALL_API_ADAPTER_FACTORIES[api_id].make_api_adapter()returncls(api_adapter)
[docs]@staticmethoddefcuda()->API:"""Returns a CUDA API object, if CUDA backend (that is, ``pycuda`` package) is available."""returnAPI.from_api_id(cuda_api_id())
[docs]@staticmethoddefopencl()->API:""" Returns an OpenCL API object, if OpenCL backend (that is, ``pyopencl`` package) is available. """returnAPI.from_api_id(opencl_api_id())
[docs]@staticmethoddefany()->API:""" Returns an API object for some available backend. Raises ``RuntimeError`` if no backends are available. """apis=API.all_available()iflen(apis)==0:raiseRuntimeError("No APIs are available. Please install either PyCUDA or PyOpenCL")returnapis[0]
def__init__(self,api_adapter:APIAdapter):self._api_adapter=api_adapterself.id=api_adapter.idself.shortcut=self.id.shortcut@propertydefplatforms(self)->list[Platform]:"""A list of this API's :py:class:`Platform` objects."""from._platformimportPlatform# noqa: PLC0415returnPlatform.all(self)def__eq__(self,other:object)->bool:returnisinstance(other,API)andself._api_adapter==other._api_adapterdef__hash__(self)->int:returnhash((type(self),self._api_adapter))def__str__(self)->str:returnf"api({self.shortcut})"