Skip to content

Added C-API hash function, used them in Python interface #491

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 9 commits into from
Jun 21, 2021
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
10 changes: 1 addition & 9 deletions conda-recipe/run_test.bat
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
call "%ONEAPI_ROOT%\compiler\latest\env\vars.bat"
if errorlevel 1 (
echo "oneAPI compiler activation failed%"
exit /b 1
)
REM conda uses %ERRORLEVEL% but FPGA scripts can set it. So it should be reseted.
set ERRORLEVEL=

@echo on

"%PYTHON%" -c "import dpctl"
if errorlevel 1 exit 1

pytest -q -ra --disable-warnings --pyargs dpctl -vv
python -m pytest -q -ra --disable-warnings --pyargs dpctl -vv
if errorlevel 1 exit 1
5 changes: 1 addition & 4 deletions conda-recipe/run_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,5 @@

set -e

# Suppress error b/c it could fail on Ubuntu 18.04
source ${ONEAPI_ROOT}/compiler/latest/env/vars.sh || true

${PYTHON} -c "import dpctl"
pytest -q -ra --disable-warnings --cov dpctl --cov-report term-missing --pyargs dpctl -vv
python -m pytest -q -ra --disable-warnings --cov dpctl --cov-report term-missing --pyargs dpctl -vv
10 changes: 10 additions & 0 deletions dpctl-capi/include/dpctl_sycl_context_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,14 @@ DPCTLContext_GetBackend(__dpctl_keep const DPCTLSyclContextRef CtxRef);
DPCTL_API
void DPCTLContext_Delete(__dpctl_take DPCTLSyclContextRef CtxRef);

/*!
* @brief Wrapper over std::hash<sycl::context>'s operator()
*
* @param CtxRef The DPCTLSyclContextRef pointer.
* @return Hash value of the underlying ``sycl::context`` instance.
* @ingroup ContextInterface
*/
DPCTL_API
size_t DPCTLContext_Hash(__dpctl_take DPCTLSyclContextRef CtxRef);

DPCTL_C_EXTERN_C_END
10 changes: 10 additions & 0 deletions dpctl-capi/include/dpctl_sycl_device_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -555,3 +555,13 @@ uint32_t DPCTLDevice_GetPreferredVectorWidthHalf(
DPCTL_API
__dpctl_give DPCTLSyclDeviceRef
DPCTLDevice_GetParentDevice(__dpctl_keep const DPCTLSyclDeviceRef DRef);

/*!
* @brief Wrapper over
* std::hash<sycl::device>'s operator()
*
* @param DRef Opaque pointer to a sycl::device
* @return Returns hash value.
*/
DPCTL_API
size_t DPCTLDevice_Hash(__dpctl_keep const DPCTLSyclDeviceRef DRef);
68 changes: 40 additions & 28 deletions dpctl-capi/include/dpctl_sycl_queue_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,11 @@ __dpctl_give DPCTLSyclQueueRef
DPCTLQueue_Copy(__dpctl_keep const DPCTLSyclQueueRef QRef);

/*!
* @brief Checks if two DPCTLSyclQueueRef objects point to the same sycl::queue.
* @brief Checks if two DPCTLSyclQueueRef objects point to the
* same ``sycl::queue``.
*
* @param QRef1 First opaque pointer to the sycl queue.
* @param QRef2 Second opaque pointer to the sycl queue.
* @param QRef1 First opaque pointer to the ``sycl::queue``.
* @param QRef2 Second opaque pointer to the ``sycl::queue``.
* @return True if the underlying sycl::queue are same, false otherwise.
* @ingroup QueueInterface
*/
Expand Down Expand Up @@ -174,11 +175,12 @@ DPCTLQueue_GetDevice(__dpctl_keep const DPCTLSyclQueueRef QRef);
* @brief Submits the kernel to the specified queue with the provided range
* argument.
*
* A wrapper over sycl::queue.submit(). The function takes an interoperability
* kernel, the kernel arguments, and a Sycl queue as input. The kernel is
* submitted as parallel_for(range<NRange>, *unwrap(KRef)).
* A wrapper over ``sycl::queue.submit()``. The function takes an
* interoperability kernel, the kernel arguments, and a ``sycl::queue`` as
* input. The kernel is submitted as
* ``parallel_for(range<NRange>, *unwrap(KRef))``.
*
* \todo sycl::buffer arguments are not supported yet.
* \todo ``sycl::buffer`` arguments are not supported yet.
* \todo Add support for id<Dims> WorkItemOffset
*
* @param KRef Opaque pointer to an OpenCL interoperability kernel
Expand All @@ -195,11 +197,11 @@ DPCTLQueue_GetDevice(__dpctl_keep const DPCTLSyclQueueRef QRef);
* dimensions.
* @param NRange Size of the gRange array.
* @param DepEvents List of dependent DPCTLSyclEventRef objects (events)
* for the kernel. We call sycl::handler.depends_on for
* each of the provided events.
* for the kernel. We call ``sycl::handler.depends_on``
* for each of the provided events.
* @param NDepEvents Size of the DepEvents list.
* @return An opaque pointer to the sycl::event returned by the
* sycl::queue.submit() function.
* @return An opaque pointer to the ``sycl::event`` returned by the
* ``sycl::queue.submit()`` function.
* @ingroup QueueInterface
*/
DPCTL_API
Expand All @@ -218,9 +220,9 @@ DPCTLQueue_SubmitRange(__dpctl_keep const DPCTLSyclKernelRef KRef,
* @brief Submits the kernel to the specified queue with the provided nd_range
* argument.
*
* A wrapper over sycl::queue.submit(). The function takes an interoperability
* kernel, the kernel arguments, and a Sycl queue as input. The kernel is
* submitted as parallel_for(nd_range<NRange>, *unwrap(KRef)).
* A wrapper over ``sycl::queue.submit()``. The function takes an
* interoperability kernel, the kernel arguments, and a Sycl queue as input.
* The kernel is submitted as ``parallel_for(nd_range<NRange>, *unwrap(KRef))``.
*
* \todo sycl::buffer arguments are not supported yet.
* \todo Add support for id<Dims> WorkItemOffset
Expand All @@ -243,11 +245,11 @@ DPCTLQueue_SubmitRange(__dpctl_keep const DPCTLSyclKernelRef KRef,
* @param NDims The number of dimensions for both local and global
* ranges.
* @param DepEvents List of dependent DPCTLSyclEventRef objects (events)
* for the kernel. We call sycl::handler.depends_on for
* each of the provided events.
* for the kernel. We call ``sycl::handler.depends_on``
* for each of the provided events.
* @param NDepEvents Size of the DepEvents list.
* @return An opaque pointer to the sycl::event returned by the
* sycl::queue.submit() function.
* @return An opaque pointer to the ``sycl::event`` returned by the
* ``sycl::queue.submit()`` function.
* @ingroup QueueInterface
*/
DPCTL_API
Expand All @@ -264,20 +266,20 @@ DPCTLQueue_SubmitNDRange(__dpctl_keep const DPCTLSyclKernelRef KRef,
size_t NDepEvents);

/*!
* @brief Calls the sycl::queue.submit function to do a blocking wait on all
* enqueued tasks in the queue.
* @brief Calls the ``sycl::queue.submit`` function to do a blocking wait on
* all enqueued tasks in the queue.
*
* @param QRef Opaque pointer to a sycl::queue.
* @param QRef Opaque pointer to a ``sycl::queue``.
* @ingroup QueueInterface
*/
DPCTL_API
void DPCTLQueue_Wait(__dpctl_keep const DPCTLSyclQueueRef QRef);

/*!
* @brief C-API wrapper for sycl::queue::memcpy, the function waits on an event
* till the memcpy operation completes.
* @brief C-API wrapper for ``sycl::queue::memcpy``, the function waits on an
* event till the memcpy operation completes.
*
* @param QRef An opaque pointer to the sycl queue.
* @param QRef An opaque pointer to the ``sycl::queue``.
* @param Dest An USM pointer to the destination memory.
* @param Src An USM pointer to the source memory.
* @param Count A number of bytes to copy.
Expand All @@ -290,10 +292,10 @@ void DPCTLQueue_Memcpy(__dpctl_keep const DPCTLSyclQueueRef QRef,
size_t Count);

/*!
* @brief C-API wrapper for sycl::queue::prefetch, the function waits on an
* @brief C-API wrapper for ``sycl::queue::prefetch``, the function waits on an
* event till the prefetch operation completes.
*
* @param QRef An opaque pointer to the sycl queue.
* @param QRef An opaque pointer to the ``sycl::queue``.
* @param Ptr An USM pointer to memory.
* @param Count A number of bytes to prefetch.
* @ingroup QueueInterface
Expand All @@ -307,7 +309,7 @@ void DPCTLQueue_Prefetch(__dpctl_keep DPCTLSyclQueueRef QRef,
* @brief C-API wrapper for sycl::queue::mem_advise, the function waits on an
* event till the operation completes.
*
* @param QRef An opaque pointer to the sycl queue.
* @param QRef An opaque pointer to the ``sycl::queue``.
* @param Ptr An USM pointer to memory.
* @param Count A number of bytes to prefetch.
* @param Advice Device-defined advice for the specified allocation.
Expand All @@ -325,10 +327,20 @@ void DPCTLQueue_MemAdvise(__dpctl_keep DPCTLSyclQueueRef QRef,
* @brief C-API wrapper for sycl::queue::is_in_order that indicates whether
* the referenced queue is in-order or out-of-order.
*
* @param QRef An opaque pointer to the sycl queue.
* @param QRef An opaque pointer to the ``sycl::queue``.
* @ingroup QueueInterface
*/
DPCTL_API
bool DPCTLQueue_IsInOrder(__dpctl_keep const DPCTLSyclQueueRef QRef);

/*!
* @brief C-API wrapper for std::hash<sycl::queue>'s operator().
*
* @param QRef An opaque pointer to the ``sycl::queue``.
* @return Hash value of the underlying ``sycl::queue`` instance.
* @ingroup QueueInterface
*/
DPCTL_API
size_t DPCTLQueue_Hash(__dpctl_keep const DPCTLSyclQueueRef QRef);

DPCTL_C_EXTERN_C_END
14 changes: 14 additions & 0 deletions dpctl-capi/source/dpctl_sycl_context_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,17 @@ DPCTLContext_GetBackend(__dpctl_keep const DPCTLSyclContextRef CtxRef)
return DPCTL_UNKNOWN_BACKEND;
}
}

size_t DPCTLContext_Hash(__dpctl_keep const DPCTLSyclContextRef CtxRef)
{
if (CtxRef) {
auto C = unwrap(CtxRef);
std::hash<context> hash_fn;
return hash_fn(*C);
}
else {
std::cerr << "Argument CtxRef is null"
<< "/n";
return 0;
}
}
15 changes: 15 additions & 0 deletions dpctl-capi/source/dpctl_sycl_device_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -690,3 +690,18 @@ __dpctl_give DPCTLDeviceVectorRef DPCTLDevice_CreateSubDevicesByAffinity(
}
return wrap(Devices);
}

size_t DPCTLDevice_Hash(__dpctl_keep const DPCTLSyclDeviceRef DRef)
{
if (DRef) {
auto D = unwrap(DRef);
std::hash<device> hash_fn;
return hash_fn(*D);
}
else {
// todo: log error
std::cerr << "Argument DRef is null"
<< "/n";
return 0;
}
}
26 changes: 23 additions & 3 deletions dpctl-capi/source/dpctl_sycl_queue_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -454,9 +454,15 @@ void DPCTLQueue_Wait(__dpctl_keep DPCTLSyclQueueRef QRef)
{
// \todo what happens if the QRef is null or a pointer to a valid sycl
// queue
auto SyclQueue = unwrap(QRef);
if (SyclQueue)
SyclQueue->wait();
if (QRef) {
auto SyclQueue = unwrap(QRef);
if (SyclQueue)
SyclQueue->wait();
}
else {
// todo: log error
std::cerr << "Argument QRef is NULL" << '\n';
}
}

void DPCTLQueue_Memcpy(__dpctl_keep const DPCTLSyclQueueRef QRef,
Expand Down Expand Up @@ -504,3 +510,17 @@ bool DPCTLQueue_IsInOrder(__dpctl_keep const DPCTLSyclQueueRef QRef)
else
return false;
}

size_t DPCTLQueue_Hash(__dpctl_keep const DPCTLSyclQueueRef QRef)
{
auto Q = unwrap(QRef);
if (Q) {
std::hash<queue> hash_fn;
return hash_fn(*Q);
}
else {
// todo: log error
std::cerr << "Argument QRef is null" << '\n';
return 0;
}
}
2 changes: 2 additions & 0 deletions dpctl-capi/tests/test_sycl_context_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ TEST_P(TestDPCTLContextInterface, ChkAreEq)
EXPECT_NO_FATAL_FAILURE(are_not_eq = DPCTLContext_AreEq(CRef1, CRef3));
EXPECT_TRUE(are_eq);
EXPECT_FALSE(are_not_eq);
EXPECT_TRUE(DPCTLContext_Hash(CRef1) == DPCTLContext_Hash(CRef2));
EXPECT_FALSE(DPCTLContext_Hash(CRef1) == DPCTLContext_Hash(CRef3));

EXPECT_NO_FATAL_FAILURE(DPCTLContext_Delete(CRef1));
EXPECT_NO_FATAL_FAILURE(DPCTLContext_Delete(CRef2));
Expand Down
2 changes: 2 additions & 0 deletions dpctl-capi/tests/test_sycl_device_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ TEST_P(TestDPCTLSyclDeviceInterface, ChkCopy)
DPCTLSyclDeviceRef Copied_DRef = nullptr;
EXPECT_NO_FATAL_FAILURE(Copied_DRef = DPCTLDevice_Copy(DRef));
EXPECT_TRUE(bool(Copied_DRef));
EXPECT_TRUE(DPCTLDevice_AreEq(DRef, Copied_DRef));
EXPECT_TRUE(DPCTLDevice_Hash(DRef) == DPCTLDevice_Hash(Copied_DRef));
EXPECT_NO_FATAL_FAILURE(DPCTLDevice_Delete(Copied_DRef));
}

Expand Down
2 changes: 2 additions & 0 deletions dpctl-capi/tests/test_sycl_queue_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,13 @@ TEST_F(TestDPCTLSyclQueueInterface, CheckAreEq)
}

EXPECT_TRUE(DPCTLQueue_AreEq(Q1, Q2));
EXPECT_TRUE(DPCTLQueue_Hash(Q1) == DPCTLQueue_Hash(Q2));
auto Q3 = DPCTLQueue_CreateForDevice(DRef, nullptr, 0);
auto Q4 = DPCTLQueue_CreateForDevice(DRef, nullptr, 0);

// These are different queues
EXPECT_FALSE(DPCTLQueue_AreEq(Q3, Q4));
EXPECT_FALSE(DPCTLQueue_Hash(Q3) == DPCTLQueue_Hash(Q4));

auto C0 = DPCTLQueue_GetContext(Q3);
auto C1 = DPCTLQueue_GetContext(Q4);
Expand Down
3 changes: 3 additions & 0 deletions dpctl/_backend.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ cdef extern from "dpctl_sycl_device_interface.h":
cdef DPCTLSyclPlatformRef DPCTLDevice_GetPlatform(
const DPCTLSyclDeviceRef DRef)
cdef const char *DPCTLDevice_GetVendor(const DPCTLSyclDeviceRef DRef)
cdef size_t DPCTLDevice_Hash(const DPCTLSyclDeviceRef DRef)
cdef bool DPCTLDevice_IsAccelerator(const DPCTLSyclDeviceRef DRef)
cdef bool DPCTLDevice_IsCPU(const DPCTLSyclDeviceRef DRef)
cdef bool DPCTLDevice_IsGPU(const DPCTLSyclDeviceRef DRef)
Expand Down Expand Up @@ -268,6 +269,7 @@ cdef extern from "dpctl_sycl_context_interface.h":
cdef size_t DPCTLContext_DeviceCount(const DPCTLSyclContextRef CRef)
cdef bool DPCTLContext_AreEq(const DPCTLSyclContextRef CtxRef1,
const DPCTLSyclContextRef CtxRef2)
cdef size_t DPCTLContext_Hash(const DPCTLSyclContextRef CRef)
cdef _backend_type DPCTLContext_GetBackend(const DPCTLSyclContextRef)
cdef void DPCTLContext_Delete(DPCTLSyclContextRef CtxRef)

Expand Down Expand Up @@ -307,6 +309,7 @@ cdef extern from "dpctl_sycl_queue_interface.h":
cdef _backend_type DPCTLQueue_GetBackend(const DPCTLSyclQueueRef Q)
cdef DPCTLSyclContextRef DPCTLQueue_GetContext(const DPCTLSyclQueueRef Q)
cdef DPCTLSyclDeviceRef DPCTLQueue_GetDevice(const DPCTLSyclQueueRef Q)
cdef size_t DPCTLQueue_Hash(const DPCTLSyclQueueRef Q)
cdef DPCTLSyclEventRef DPCTLQueue_SubmitRange(
const DPCTLSyclKernelRef Ref,
const DPCTLSyclQueueRef QRef,
Expand Down
8 changes: 8 additions & 0 deletions dpctl/_sycl_context.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ from ._backend cimport ( # noqa: E211
DPCTLContext_Delete,
DPCTLContext_DeviceCount,
DPCTLContext_GetDevices,
DPCTLContext_Hash,
DPCTLDevice_Copy,
DPCTLDevice_Delete,
DPCTLDeviceMgr_GetCachedContext,
Expand Down Expand Up @@ -335,6 +336,13 @@ cdef class SyclContext(_SyclContext):
else:
return False

def __hash__(self):
"""
Returns a hash value by hashing the underlying ``sycl::context`` object.

"""
return DPCTLContext_Hash(self._ctxt_ref)

cdef DPCTLSyclContextRef get_context_ref(self):
return self._ctxt_ref

Expand Down
8 changes: 8 additions & 0 deletions dpctl/_sycl_device.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ from ._backend cimport ( # noqa: E211
DPCTLDevice_GetSubGroupIndependentForwardProgress,
DPCTLDevice_GetVendor,
DPCTLDevice_HasAspect,
DPCTLDevice_Hash,
DPCTLDevice_IsAccelerator,
DPCTLDevice_IsCPU,
DPCTLDevice_IsGPU,
Expand Down Expand Up @@ -709,6 +710,13 @@ cdef class SyclDevice(_SyclDevice):
+ "] at {}>".format(hex(id(self)))
)

def __hash__(self):
"""
Returns a hash value by hashing the underlying ``sycl::device`` object.

"""
return DPCTLDevice_Hash(self._device_ref)

cdef list create_sub_devices_equally(self, size_t count):
""" Returns a list of sub-devices partitioned from this SYCL device
based on the ``count`` parameter.
Expand Down
8 changes: 8 additions & 0 deletions dpctl/_sycl_queue.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ from ._backend cimport ( # noqa: E211
DPCTLQueue_GetBackend,
DPCTLQueue_GetContext,
DPCTLQueue_GetDevice,
DPCTLQueue_Hash,
DPCTLQueue_IsInOrder,
DPCTLQueue_MemAdvise,
DPCTLQueue_Memcpy,
Expand Down Expand Up @@ -863,6 +864,13 @@ cdef class SyclQueue(_SyclQueue):
else:
return "<dpctl." + self.__name__ + " at {}>".format(hex(id(self)))

def __hash__(self):
"""
Returns a hash value by hashing the underlying ``sycl::queue`` object.

"""
return DPCTLQueue_Hash(self._queue_ref)

def _get_capsule(self):
cdef DPCTLSyclQueueRef QRef = NULL
QRef = DPCTLQueue_Copy(self._queue_ref)
Expand Down
Loading