Skip to content

Remove the DPCTLQueueMgr_* and device_context API from dpctl #1576

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions docs/docfiles/user_guides/QuickStart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -259,21 +259,24 @@ library.
set +xe
rm -rf build
mkdir build
pushd build
pushd build || exit 1

INSTALL_PREFIX=`pwd`/../install
INSTALL_PREFIX=$(pwd)/../install
rm -rf ${INSTALL_PREFIX}
export ONEAPI_ROOT=/opt/intel/oneapi
DPCPP_ROOT=${ONEAPI_ROOT}/compiler/latest/linux

cmake \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_C_COMPILER=icx \
-DCMAKE_CXX_COMPILER=dpcpp \
-DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX} \
-DCMAKE_PREFIX_PATH=${INSTALL_PREFIX} \
-DDPCPP_INSTALL_DIR=${DPCPP_ROOT} \
-DCMAKE_C_COMPILER:PATH=${DPCPP_ROOT}/bin/icx \
-DCMAKE_CXX_COMPILER:PATH=${DPCPP_ROOT}/bin/dpcpp \
-DDPCTL_ENABLE_L0_PROGRAM_CREATION=ON \
-DDPCTL_BUILD_CAPI_TESTS=ON \
-DDPCTL_GENERATE_COVERAGE=ON \
..

make V=1 -n -j 4 && make check && make install

popd || exit 1
1 change: 0 additions & 1 deletion dpctl/__init__.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,3 @@ from dpctl._sycl_device_factory cimport *
from dpctl._sycl_event cimport *
from dpctl._sycl_platform cimport *
from dpctl._sycl_queue cimport *
from dpctl._sycl_queue_manager cimport *
31 changes: 2 additions & 29 deletions dpctl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,7 @@

Dpctl implements a subset of SYCL's API providing wrappers for the
SYCL runtime classes described in :sycl_runtime_classes:`Section 4.6 <>` of
the :sycl_spec_2020:`SYCL 2020 spec <>`. Note that the SYCL
``device_selector`` class is not implemented, instead there are device
selection helper functions that can be used to simulate the same behavior.
Dpctl implements the ``ONEPI::filter_selector`` extension that is included
in Intel's DPC++ SYCL compiler.

The module also includes a global SYCL queue manager. The queue manager
provides convenience functions to create a global instance of
a :class:`dpctl.SyclQueue`, to create a nested stack of queue objects, and
to create a queue object for use only within a specific scope.
the :sycl_spec_2020:`SYCL 2020 spec <>`.
"""
__author__ = "Intel Corp."

Expand Down Expand Up @@ -61,17 +52,7 @@
SyclQueue,
SyclQueueCreationError,
)
from ._sycl_queue_manager import (
device_context,
get_current_backend,
get_current_device_type,
get_current_queue,
get_device_cached_queue,
get_num_activated_queues,
is_in_device_context,
nested_context_factories,
set_global_queue,
)
from ._sycl_queue_manager import get_device_cached_queue
from ._sycl_timer import SyclTimer
from ._version import get_versions
from .enum_types import (
Expand Down Expand Up @@ -120,15 +101,7 @@
"SyclQueueCreationError",
]
__all__ += [
"device_context",
"get_current_backend",
"get_current_device_type",
"get_current_queue",
"get_device_cached_queue",
"get_num_activated_queues",
"is_in_device_context",
"nested_context_factories",
"set_global_queue",
]
__all__ += [
"device_type",
Expand Down
10 changes: 0 additions & 10 deletions dpctl/_backend.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -432,16 +432,6 @@ cdef extern from "syclinterface/dpctl_sycl_queue_interface.h":
cdef bool DPCTLQueue_HasEnableProfiling(const DPCTLSyclQueueRef QRef)


cdef extern from "syclinterface/dpctl_sycl_queue_manager.h":
cdef DPCTLSyclQueueRef DPCTLQueueMgr_GetCurrentQueue()
cdef bool DPCTLQueueMgr_GlobalQueueIsCurrent()
cdef bool DPCTLQueueMgr_IsCurrentQueue(const DPCTLSyclQueueRef QRef)
cdef void DPCTLQueueMgr_PopQueue()
cdef void DPCTLQueueMgr_PushQueue(const DPCTLSyclQueueRef dRef)
cdef void DPCTLQueueMgr_SetGlobalQueue(const DPCTLSyclQueueRef dRef)
cdef size_t DPCTLQueueMgr_GetQueueStackSize()


cdef extern from "syclinterface/dpctl_sycl_usm_interface.h":
cdef DPCTLSyclUSMRef DPCTLmalloc_shared(
size_t size,
Expand Down
4 changes: 0 additions & 4 deletions dpctl/_sycl_queue_manager.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,4 @@ from ._sycl_device cimport SyclDevice
from ._sycl_queue cimport SyclQueue


cpdef SyclQueue get_current_queue()
cpdef get_current_device_type ()
cpdef get_current_backend()

cpdef object get_device_cached_queue(object)
266 changes: 0 additions & 266 deletions dpctl/_sycl_queue_manager.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -19,284 +19,18 @@
# cython: linetrace=True

import logging
from contextlib import ExitStack, contextmanager
from contextvars import ContextVar

from .enum_types import backend_type, device_type

from ._backend cimport ( # noqa: E211
DPCTLQueueMgr_GetCurrentQueue,
DPCTLQueueMgr_GetQueueStackSize,
DPCTLQueueMgr_GlobalQueueIsCurrent,
DPCTLQueueMgr_PopQueue,
DPCTLQueueMgr_PushQueue,
DPCTLQueueMgr_SetGlobalQueue,
DPCTLSyclQueueRef,
_backend_type,
_device_type,
)
from ._sycl_context cimport SyclContext
from ._sycl_device cimport SyclDevice

__all__ = [
"_global_device_queue_cache",
"device_context",
"get_current_backend",
"get_current_device_type",
"get_current_queue",
"get_device_cached_queue",
"get_num_activated_queues",
"is_in_device_context",
"set_global_queue",
]

_logger = logging.getLogger(__name__)


cdef class _SyclQueueManager:
""" Provides a SYCL queue manager interface for Python.
"""

def _set_as_current_queue(self, arg):
cdef SyclQueue q
cdef DPCTLSyclQueueRef queue_ref = NULL

if isinstance(arg, SyclQueue):
q_obj = arg
else:
q_obj = SyclQueue(arg)

q = <SyclQueue> q_obj
queue_ref = q.get_queue_ref()
DPCTLQueueMgr_PushQueue(queue_ref)

return q_obj

def _remove_current_queue(self):
DPCTLQueueMgr_PopQueue()

cpdef get_current_backend(self):
"""
Returns the backend for the current queue as a `backend_type` enum.

Returns:
backend_type: The SYCL backend for the currently selected queue.
"""
return self.get_current_queue().backend

cpdef get_current_device_type(self):
"""
Returns current device type as a `device_type` enum.

Returns:
device_type: The SYCL device type for the currently selected queue.
Possible values can be gpu, cpu, accelerator, or host.
"""
return self.get_current_queue().sycl_device.device_type

cpdef SyclQueue get_current_queue(self):
"""
Returns the currently activated SYCL queue as a new SyclQueue object.

Returns:
SyclQueue: If there is a currently active SYCL queue that queue
is returned wrapped in a SyclQueue object. The SyclQueue object
owns a copy of the currently active SYCL queue as an opaque
`DPCTLSyclQueueRef` pointer. The pointer is freed when the SyclQueue
is garbage collected.

Raises:
SyclQueueCreationError: If no currently active SYCL queue found.
"""
return SyclQueue._create(DPCTLQueueMgr_GetCurrentQueue())

def get_num_activated_queues(self):
"""
Returns the number of currently activated queues for this thread.

Whenever a program's control enters a :func:`dpctl.device_context()`
scope, either a new SYCL queue is created or a previously created
queue is retrieved from a cache and yielded. The queue yielded by the
context manager is termed to be "activated". If a program creates
multiple nested :func:`dpctl.device_context()` scopes then multiple
queues can be activated at the same time, although only the latest
activated queue is usable directly via calling
:func:`dpctl.get_current_queue()`. This function returns the number of
currently activated queues.

Returns:
int: The number of currently activated queues.

"""
return DPCTLQueueMgr_GetQueueStackSize()

def is_in_device_context(self):
"""
Checks if the control is inside a :func:`dpctl.device_context()` scope.

Returns:
bool: True if the control is within a
:func:`dpctl.device_context()` scope, otherwise False.
"""
cdef int inCtx = DPCTLQueueMgr_GlobalQueueIsCurrent()
return not bool(inCtx)

def set_global_queue(self, arg):
"""
Sets the global queue to the SYCL queue specified explicitly,
or created from given arguments.

Args:
arg: An instance of :class:`dpctl.SyclQueue` or a filter selector
string to be used to construct a :class:`dpctl.SyclQueue`. The
queue is stored in the dpctl queue manager as the default queue.
Raises:
SyclQueueCreationError: If a SYCL queue could not be created.
"""
cdef SyclQueue q
cdef DPCTLSyclQueueRef queue_ref = NULL

if type(arg) is SyclQueue:
q = <SyclQueue> arg
else:
q_obj = SyclQueue(arg)
q = <SyclQueue> q_obj

queue_ref = q.get_queue_ref()
DPCTLQueueMgr_SetGlobalQueue(queue_ref)


# This private instance of the _SyclQueueManager should not be directly
# accessed outside the module.
_mgr = _SyclQueueManager()

# Global bound functions
get_num_activated_queues = _mgr.get_num_activated_queues
set_global_queue = _mgr.set_global_queue
is_in_device_context = _mgr.is_in_device_context


cpdef SyclQueue get_current_queue():
"""
Returns the currently activate SYCL queue as a new SyclQueue object.

Returns:
SyclQueue: If there is a currently active SYCL queue that queue
is returned wrapped in a SyclQueue object. The SyclQueue object
owns a copy of the currently active SYCL queue as an opaque
`DPCTLSyclQueueRef` pointer. The pointer is freed when the SyclQueue
is garbage collected.

Raises:
SyclQueueCreationError: If no currently active SYCL queue found.
"""
return _mgr.get_current_queue()


cpdef get_current_device_type():
"""
Returns current device type as a `device_type` enum.

Returns:
device_type: The SYCL device type for the currently selected queue.
Possible values can be gpu, cpu, accelerator, or host.
"""
return _mgr.get_current_device_type()


cpdef get_current_backend():
"""
Returns the backend for the current queue as a `backend_type` enum.

Returns:
backend_type: The SYCL backend for the currently selected queue.
"""
return _mgr.get_current_backend()


nested_context_factories = []


def _get_nested_contexts(ctxt):
_help_numba_dppy()
return (factory(ctxt) for factory in nested_context_factories)


def _help_numba_dppy():
"""Import numba-dppy for registering nested contexts"""
try:
import numba_dppy
except Exception:
pass


@contextmanager
def device_context(arg):
"""
Yields a SYCL queue corresponding to the input queue object, device object,
or device filter selector string.

This context manager "activates", *i.e.*, sets as the currently usable
queue, the SYCL queue defined by the argument `arg`.
The activated queue is yielded by the context manager and can also be
accessed by any subsequent call to :func:`dpctl.get_current_queue()` inside
the context manager's scope. The yielded queue is removed as the currently
usable queue on exiting the context manager.

You can register context factory in the list of factories.
This context manager uses context factories to create and activate nested contexts.

Args:
arg : A :class:`dpctl.SyclQueue` object, or a :class:`dpctl.SyclDevice`
object, or a filter selector string.

Yields:
:class:`dpctl.SyclQueue`: A SYCL queue corresponding to the specified
input device, queue, or filter string.

Raises:
SyclQueueCreationError: If the SYCL queue creation failed.

:Example:
The following example sets current queue targeting specific device
indicated with filter selector string in the scope of `with` block:

.. code-block:: python

import dpctl
with dpctl.device_context("level0:gpu:0"):
do_something_on_gpu0()

The following example registers nested context factory:

.. code-block:: python

import dctl

def factory(sycl_queue):
...
return context

dpctl.nested_context_factories.append(factory)

"""
ctxt = None
try:
ctxt = _mgr._set_as_current_queue(arg)
with ExitStack() as stack:
for nested_context in _get_nested_contexts(ctxt):
stack.enter_context(nested_context)
yield ctxt
finally:
# Code to release resource
if ctxt:
_logger.debug(
"Removing the queue from the stack of active queues")
_mgr._remove_current_queue()
else:
_logger.debug("No queue was created so nothing to do")


cdef class _DeviceDefaultQueueCache:
cdef dict __device_queue_map__

Expand Down
Loading