diff --git a/dpctl/tests/test_utils.py b/dpctl/tests/test_utils.py index 472edd2ff2..65f194ecf8 100644 --- a/dpctl/tests/test_utils.py +++ b/dpctl/tests/test_utils.py @@ -92,3 +92,25 @@ def test_order_manager(): _passed = True finally: assert _passed + + +def test_no_op_order_manager(): + try: + q = dpctl.SyclQueue(property=("in_order",)) + except dpctl.SyclQueueCreationError: + pytest.skip("Queue could not be created for default-selected device") + assert q.is_in_order + _mngr = dpctl.utils.SequentialOrderManager[q] + assert _mngr.num_host_task_events == 0 + assert _mngr.num_submitted_events == 0 + assert isinstance(_mngr.submitted_events, list) + assert len(_mngr.submitted_events) == 0 + assert isinstance(_mngr.host_task_events, list) + assert len(_mngr.host_task_events) == 0 + _mngr.add_event_pair(dpctl.SyclEvent(), dpctl.SyclEvent()) + _mngr.add_event_pair([dpctl.SyclEvent()], dpctl.SyclEvent()) + _mngr.add_event_pair(dpctl.SyclEvent(), [dpctl.SyclEvent()]) + # waits on queue + _mngr.wait() + cpy = _mngr.__copy__() + del cpy diff --git a/dpctl/utils/_order_manager.py b/dpctl/utils/_order_manager.py index fbe2c47763..6374b4fc4e 100644 --- a/dpctl/utils/_order_manager.py +++ b/dpctl/utils/_order_manager.py @@ -1,6 +1,7 @@ import weakref from collections import defaultdict from contextvars import ContextVar +from typing import Union from .._sycl_event import SyclEvent from .._sycl_queue import SyclQueue @@ -64,6 +65,39 @@ def __copy__(self): return res +class _NoOpOrderManager: + """Dummy order manager used when queue is in-order.""" + + def __init__(self, q: SyclQueue): + self._queue = q + + def add_event_pair(self, _host_task_ev, _comp_ev): + pass + + @property + def num_host_task_events(self): + return 0 + + @property + def num_submitted_events(self): + return 0 + + @property + def host_task_events(self): + return [] + + @property + def submitted_events(self): + return [] + + def wait(self): + # to imitate SequentialOrderManager, wait on the in-order queue + self._queue.wait() + + def __copy__(self): + return _NoOpOrderManager(self._queue) + + class SyclQueueToOrderManagerMap: """Utility class used to ensure sequential ordering of offloaded tasks when passed to order manager.""" @@ -74,11 +108,16 @@ def __init__(self): default=defaultdict(_SequentialOrderManager), ) - def __getitem__(self, q: SyclQueue) -> _SequentialOrderManager: + def __getitem__( + self, q: SyclQueue + ) -> Union[_SequentialOrderManager, _NoOpOrderManager]: """Get order manager for given SyclQueue""" - _local = self._map.get() if not isinstance(q, SyclQueue): raise TypeError(f"Expected `dpctl.SyclQueue`, got {type(q)}") + if q.is_in_order: + # we don't need to cache the NoOpOrderManager since it's stateless + return _NoOpOrderManager(q) + _local = self._map.get() if q in _local: return _local[q] else: