Skip to content

Commit ca1761d

Browse files
committed
Add python interface for ipc memory handles.
1 parent 72b26fd commit ca1761d

3 files changed

Lines changed: 44 additions & 11 deletions

File tree

pygpu/gpuarray.pxd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,9 @@ cdef extern from "gpuarray/array.h":
196196

197197
cdef extern from "gpuarray/extension.h":
198198
void *gpuarray_get_extension(const char *)
199+
ctypedef struct GpuArrayIpcMemHandle:
200+
pass
201+
199202
cdef int GPUARRAY_CUDA_CTX_NOFREE
200203

201204
cdef type get_exc(int errcode)

pygpu/gpuarray.pyx

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,6 +1424,28 @@ def _concatenate(list al, unsigned int axis, int restype, object cls,
14241424
finally:
14251425
PyMem_Free(als)
14261426

1427+
cdef int (*cuda_get_ipc_handle)(gpudata *, GpuArrayIpcMemHandle *)
1428+
cdef gpudata *(*cuda_open_ipc_handle)(gpucontext *, GpuArrayIpcMemHandle *, size_t)
1429+
1430+
cuda_get_ipc_handle = <int (*)(gpudata *, GpuArrayIpcMemHandle *)>gpuarray_get_extension("cuda_get_ipc_handle")
1431+
cuda_open_ipc_handle = <gpudata *(*)(gpucontext *, GpuArrayIpcMemHandle *, size_t)>gpuarray_get_extension("cuda_open_ipc_handle")
1432+
1433+
def open_ipc_handle(GpuContext c, bytes hpy, size_t l):
1434+
"""
1435+
Open an IPC handle to get a new GpuArray from it.
1436+
"""
1437+
cdef char *b
1438+
cdef GpuArrayIpcMemHandle h
1439+
cdef gpudata *d
1440+
1441+
b = hpy
1442+
memcpy(&h, b, sizeof(h))
1443+
1444+
d = cuda_open_ipc_handle(c.ctx, &h, l)
1445+
if d is NULL:
1446+
raise GpuArrayException, "could not open handle"
1447+
return <size_t>d
1448+
14271449
cdef class GpuArray:
14281450
"""
14291451
Device array
@@ -1561,6 +1583,19 @@ cdef class GpuArray:
15611583
raise ValueError, "GpuArray and Numpy array do not have the same size in bytes"
15621584
array_read(np.PyArray_DATA(dst), sz, self)
15631585

1586+
def get_ipc_handle(self):
1587+
cdef GpuArrayIpcMemHandle h
1588+
cdef int err
1589+
if cuda_get_ipc_handle is NULL:
1590+
raise SystemError, "Could not get necessary extension"
1591+
if self.context.kind == 'cuda':
1592+
raise ValueError, "Only works for cuda contexts"
1593+
err = cuda_get_ipc_handle(self.ga.data, &h)
1594+
if err != GA_NO_ERROR:
1595+
raise get_exc(err), GpuArray_error(&self.ga, err)
1596+
res = <bytes>(<char *>&h)[:sizeof(h)]
1597+
return res
1598+
15641599
def __array__(self):
15651600
"""
15661601
__array__()

src/gpuarray_buffer_cuda.c

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -560,27 +560,22 @@ static gpudata *cuda_alloc(gpucontext *c, size_t size, void *data, int flags,
560560
return res;
561561
}
562562

563-
GpuArrayIpcMemHandle cuda_get_ipc_handle(gpudata *d) {
564-
CUipcMemHandle h = {{0}};
565-
563+
int cuda_get_ipc_handle(gpudata *d, GpuArrayIpcMemHandle *h) {
566564
ASSERT_BUF(d);
567565
cuda_enter(d->ctx);
568-
d->ctx->err = cuIpcGetMemHandle(&h, d->ptr);
566+
CUDA_EXIT_ON_ERROR(d->ctx,
567+
cuIpcGetMemHandle((CUipcMemHandle *)h, d->ptr));
569568
cuda_exit(d->ctx);
570-
/* You need to do this stupid dance because direct casting of
571-
* structures is not allowed */
572-
return *((GpuArrayIpcMemHandle *)&h);
569+
return GA_NO_ERROR;
573570
}
574571

575-
gpudata *cuda_open_ipc_handle(gpucontext *c, GpuArrayIpcMemHandle h, size_t sz) {
572+
gpudata *cuda_open_ipc_handle(gpucontext *c, GpuArrayIpcMemHandle *h, size_t sz) {
576573
CUdeviceptr p;
577574
cuda_context *ctx = (cuda_context *)c;
578575
gpudata *d = NULL;
579576

580577
cuda_enter(ctx);
581-
/* You need to do this stupid dance because direct casting of
582-
* structures is not allowed */
583-
ctx->err = cuIpcOpenMemHandle(&p, *((CUipcMemHandle *)&h),
578+
ctx->err = cuIpcOpenMemHandle(&p, *((CUipcMemHandle *)h),
584579
CU_IPC_MEM_LAZY_ENABLE_PEER_ACCESS);
585580
if (ctx->err == CUDA_SUCCESS) {
586581
d = cuda_make_buf(ctx, p, sz);

0 commit comments

Comments
 (0)