Add Python bindings for SYCL IPC memory via dpctl#2331
Conversation
Add inter-process communication (IPC) support for SYCL USM memory, enabling
zero-copy GPU memory sharing across processes. It wraps
sycl::ext::oneapi::experimental::ipc::memory (get/open/close/put).
C API (libsyclinterface):
- dpctl_sycl_ipc_memory_interface.h: declares DPCTLIPCMem_GetHandle,
DPCTLIPCMem_OpenHandle, DPCTLIPCMem_CloseHandle, DPCTLIPCMem_FreeHandleData
- dpctl_sycl_ipc_memory_interface.cpp: implements the C API by calling the
SYCL experimental ipc::memory functions; auto-discovered by CMake.
Cython declarations:
- _backend.pxd: extern block for the 4 new C functions
Python subpackage (dpctl.ipc):
- IPCMemoryHandle: Cython extension class wrapping IPC memory export/import
__init__(usm_memory): calls get() + put(), stores handle as bytes
to_bytes(): serializable payload for cross-process transport
open(handle_bytes, device, nbytes): returns MemoryUSMDevice
close_mapping(usm_memory): explicitly closes an IPC mapping
Signed-off-by: Zhan Xue <zhan.xue@intel.com>
| cdef class IPCMemoryHandle: | ||
| """Wrapper around a SYCL IPC memory handle. | ||
|
|
||
| Instances are created by passing a :class:`dpctl.memory.MemoryUSMDevice` |
There was a problem hiding this comment.
if this docstring is accurate and the extension only works with MemoryUSMDevice, then shouldn't we add isinstance check below to guarantee it's device memory?
Is it a requirement that it be a USM device allocation, or can host and/or shared work?
| raise RuntimeError( | ||
| "DPCTLIPCMem_GetHandle failed — device may not support " | ||
| "aspect::ext_oneapi_ipc_memory" | ||
| ) |
There was a problem hiding this comment.
can we also add this aspect to dpctl.SyclDevice as part of this PR? In general to users, it would be helpful to be able to check, and then we can perform a check in here as well
| usm_memory._opaque_ptr = NULL | ||
| usm_memory._memory_ptr = NULL | ||
| usm_memory.nbytes = 0 |
There was a problem hiding this comment.
this seems a bit dangerous for users
I think it would make the most sense to instead, since _opaque_ptr is std::shared_ptr, share the shared_ptr with the memory object shared pointer if possible
| context = device.sycl_platform.default_context | ||
|
|
||
| cdef DPCTLSyclContextRef ctx_ref = context.get_context_ref() | ||
| cdef DPCTLSyclDeviceRef dev_ref = device.get_device_ref() |
There was a problem hiding this comment.
if we add the aspect check, we can add a check here for the device
| # distutils: language = c++ | ||
| # cython: language_level=3 | ||
|
|
||
| """Declarations for the IPCMemoryHandle Cython extension type.""" |
There was a problem hiding this comment.
I'm conflicted on whether this belongs in a separate namespace or not. So far, we've been free with incorporating extensions into the main dpctl namespace, as long as we have fall-backs so that they don't crash, etc. when the extension is unavailable. This will enable us to use AdaptiveCpp in the future.
Having an entire submodule not be built is a bit different. Perhaps instead we can move this into dpctl.memory and implement fallbacks in the C-API and an is_available free function like we have for WorkGroupMemory, etc. to check for it
Add inter-process communication (IPC) support for SYCL USM memory, enabling zero-copy GPU memory sharing across processes. It wraps sycl::ext::oneapi::experimental::ipc::memory (get/open/close/put).
C API (libsyclinterface):
Cython declarations:
Python subpackage (dpctl.ipc):
Test In Docker (oneAPI 2026.0 installed):