# Data Parallel Control (dpctl)## Copyright 2020-2025 Intel Corporation## Licensed under the Apache License, Version 2.0 (the "License");# you may not use this file except in compliance with the License.# You may obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an "AS IS" BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License.importdpctlfromdpctl._sycl_device_factoryimport_cached_default_devicefromdpctl._sycl_queue_managerimportget_device_cached_queue__doc__="Implementation of array API mandated Device class"
[docs]classDevice:""" An object representing Data-API concept of device. This is a wrapper around :class:`dpctl.SyclQueue` with custom formatting. The class does not have public constructor, but a class method :meth:`dpctl.tensor.Device.create_device` to construct it from `device` keyword argument in Array-API functions. Instance can be queried for ``sycl_queue``, ``sycl_context``, or ``sycl_device``. """__device_queue_map__={}sycl_queue_=Nonedef__new__(cls,*args,**kwargs):raiseTypeError("No public constructor")@classmethoddefcreate_device(cls,device=None):"""Device.create_device(device=None) Creates instance of Device from argument. Args: device: Device specification, i.e. `None`, :class:`.Device`, :class:`dpctl.SyclQueue`, or a :class:`dpctl.SyclDevice` corresponding to a root SYCL device. Raises: ValueError: if an instance of :class:`dpctl.SycDevice` corresponding to a sub-device was specified as the argument SyclQueueCreationError: if :class:`dpctl.SyclQueue` could not be created from the argument """dev=deviceobj=super().__new__(cls)ifisinstance(dev,Device):obj.sycl_queue_=dev.sycl_queueelifisinstance(dev,dpctl.SyclQueue):obj.sycl_queue_=develifisinstance(dev,dpctl.SyclDevice):par=dev.parent_deviceifparisNone:obj.sycl_queue_=get_device_cached_queue(dev)else:raiseValueError(f"Using non-root device {dev} to specify offloading ""target is ambiguous. Please use dpctl.SyclQueue ""targeting this device")else:ifdevisNone:_dev=_cached_default_device()else:_dev=dpctl.SyclDevice(dev)obj.sycl_queue_=get_device_cached_queue(_dev)returnobj@propertydefsycl_queue(self):""" :class:`dpctl.SyclQueue` used to offload to this :class:`.Device`. """returnself.sycl_queue_@propertydefsycl_context(self):""" :class:`dpctl.SyclContext` associated with this :class:`.Device`. """returnself.sycl_queue_.sycl_context@propertydefsycl_device(self):""" :class:`dpctl.SyclDevice` targeted by this :class:`.Device`. """returnself.sycl_queue_.sycl_devicedef__repr__(self):try:sd=self.sycl_deviceexceptAttributeErrorasexc:raiseValueError(f"Instance of {self.__class__} is not initialized")fromexctry:fs=sd.filter_stringreturnf"Device({fs})"exceptTypeError:# This is a sub-devicereturnrepr(self.sycl_queue)defprint_device_info(self):"Outputs information about targeted SYCL device"self.sycl_device.print_device_info()defwait(self):""" Call ``wait`` method of the underlying ``sycl_queue``. """self.sycl_queue_.wait()def__eq__(self,other):"""Equality comparison based on underlying ``sycl_queue``."""ifisinstance(other,Device):returnself.sycl_queue.__eq__(other.sycl_queue)elifisinstance(other,dpctl.SyclQueue):returnself.sycl_queue.__eq__(other)returnFalsedef__hash__(self):"""Compute object's hash value."""returnself.sycl_queue.__hash__()
defnormalize_queue_device(sycl_queue=None,device=None):"""normalize_queue_device(sycl_queue=None, device=None) Utility to process exclusive keyword arguments 'device' and 'sycl_queue' in functions of `dpctl.tensor`. Args: sycl_queue (:class:`dpctl.SyclQueue`, optional): explicitly indicates where USM allocation is done and the population code (if any) is executed. Value `None` is interpreted as get the SYCL queue from `device` keyword, or use default queue. Default: None device (string, :class:`dpctl.SyclDevice`, :class:`dpctl.SyclQueue, :class:`dpctl.tensor.Device`, optional): array-API keyword indicating non-partitioned SYCL device where array is allocated. Returns :class:`dpctl.SyclQueue` object implied by either of provided keywords. If both are None, `dpctl.SyclQueue()` is returned. If both are specified and imply the same queue, `sycl_queue` is returned. Raises: TypeError: if argument is not of the expected type, or keywords imply incompatible queues. """q=sycl_queued=deviceifqisNone:d=Device.create_device(d)returnd.sycl_queueifnotisinstance(q,dpctl.SyclQueue):raiseTypeError(f"Expected dpctl.SyclQueue, got {type(q)}")ifdisNone:returnqd=Device.create_device(d)qq=dpctl.utils.get_execution_queue((q,d.sycl_queue,))ifqqisNone:raiseTypeError("sycl_queue and device keywords can not be both specified")returnqq