Currently the attributes of StridedMemoryView are as follows:
| # TODO: switch to use Cython's cdef typing? |
| ptr: int=None |
| shape: tuple=None |
| strides: tuple=None# in counts, not bytes |
| dtype: numpy.dtype =None |
| device_id: int=None# -1 for CPU |
| device_accessible: bool=None |
| readonly: bool=None |
| obj: Any =None |
There is a todo in the code noting that this is worth converting to Cython types. Would also support this recommendation
When accessing things like shape or strides in Cython, one ideally wants a C array type of some form (pointer, typed-memoryview, dynamic array, etc.) that can easily be iterated over in C for-loops. As these attributes are currently accessing them requires calling the CPython API to get the length, each value, coerce them to C friendly types, etc.
This is especially important for things like ptr, which gets accessed regularly. So having a fast access C-type really helps
If we look at the Python Buffer Protocol (PEP 3118), they have the following definition for Py_buffer (their equivalent type):
typedefstruct {
void*buf;
PyObject*obj; /* owned reference */Py_ssize_tlen;
Py_ssize_titemsize; /* This is Py_ssize_t so it can be pointed to by strides in simple case.*/intreadonly;
intndim;
char*format;
Py_ssize_t*shape;
Py_ssize_t*strides;
Py_ssize_t*suboffsets;
void*internal;
} Py_buffer;They also require users to call PyObject_GetBuffer to produce a buffer object and PyBuffer_Release to release a buffer object. This handles any memory allocation/deallocation for shape, strides, etc.. It also handles refcounting for obj. This functionality is wonderful to use
The lack of these semantics has made working with DLPack a chore
Thinking about how to map the C-like struct above to Cython/Python. A few things stick out
Some of these Cython can translate between Python/Cython/C like Py_ssize_t (effectively ssize_t in C (PEP 353)) to Python int's when needed.
Others can be coerced like char* to bytes (though usually one will want to decode/encode to/from str)
Still others could be translated well by Cython as long as they are typed appropriately. For example void* doesn't translate well to Python. However uintptr_t does behave like a pointer in C (sometimes with a cast) and like a Python int. Cython will handle the translation for us. Similarly bint for readonly works better when capturing Python's bool semantics while still working in C.
With a typed memoryview, it is possible to wrangle Py_ssize_t* into something better behaved like Py_ssize_t[::1], which can then move more easily between Python & Cython.
Also note that format above is a string specifying the format type according to the Python Buffer Protocol. NumPy is also able to consume and produce such format strings
This led RAPIDS to this approach:
cdef class Array:
cdef readonly uintptr_t ptr
cdef readonly bint readonly
cdef readonly object obj
cdef readonly Py_ssize_t itemsize
cdef readonly Py_ssize_t ndim
cdef Py_ssize_t[::1] shape_mv
cdef Py_ssize_t[::1] strides_mv
cdef readonly bint cuda
If StridedMemoryView is used with C/C++ directly, it may make sense to actually type a public C struct in Cython. Then this could be leveraged in C/C++ code that can hand such objects to or receive them from CUDA-Python. For example
# filename: strided_memory_view.pxdfrom libc.stdint cimport uintptr_t
cdef public struct CStridedMemoryView:
uintptr_t ptr
ssize_t* shape
ssize_t* strides
char* format
int device_id
bint device_accessible
bint readonly
void* obj
cdef class StridedMemoryView:
CStridedMemoryView data
// filename: my_program.c#include<stdbool.h>#include<stdint.h>#include<sys/types.h>#include"strided_memory_view.h"staticconstchar*s="Hello World!";
staticconstssize_ts_len=13;
intmain() {
CStridedMemoryViewst;
st.ptr= (uintptr_t)s;
st.shape=&s_len;
st.readonly= true;
// ...return0;
}Though there can be other valid ways to go
Currently the attributes of
StridedMemoryVieware as follows:cuda-python/cuda_core/cuda/core/experimental/_memoryview.pyx
Lines 24 to 32 in 8c841cd
There is a todo in the code noting that this is worth converting to Cython types. Would also support this recommendation
When accessing things like
shapeorstridesin Cython, one ideally wants a C array type of some form (pointer, typed-memoryview, dynamic array, etc.) that can easily be iterated over in Cfor-loops. As these attributes are currently accessing them requires calling the CPython API to get the length, each value, coerce them to C friendly types, etc.This is especially important for things like
ptr, which gets accessed regularly. So having a fast access C-type really helpsIf we look at the Python Buffer Protocol (PEP 3118), they have the following definition for
Py_buffer(their equivalent type):They also require users to call
PyObject_GetBufferto produce a buffer object andPyBuffer_Releaseto release a buffer object. This handles any memory allocation/deallocation forshape,strides, etc.. It also handles refcounting forobj. This functionality is wonderful to useThe lack of these semantics has made working with
DLPacka choreThinking about how to map the C-like
structabove to Cython/Python. A few things stick outSome of these Cython can translate between Python/Cython/C like
Py_ssize_t(effectivelyssize_tin C (PEP 353)) to Pythonint's when needed.Others can be coerced like
char*tobytes(though usually one will want todecode/encodeto/fromstr)Still others could be translated well by Cython as long as they are typed appropriately. For example
void*doesn't translate well to Python. Howeveruintptr_tdoes behave like a pointer in C (sometimes with a cast) and like a Pythonint. Cython will handle the translation for us. Similarlybintfor readonly works better when capturing Python'sboolsemantics while still working in C.With a typed
memoryview, it is possible to wranglePy_ssize_t*into something better behaved likePy_ssize_t[::1], which can then move more easily between Python & Cython.Also note that
formatabove is a string specifying the format type according to the Python Buffer Protocol. NumPy is also able to consume and produce such format stringsThis led RAPIDS to this approach:
If
StridedMemoryViewis used with C/C++ directly, it may make sense to actually type a public Cstructin Cython. Then this could be leveraged in C/C++ code that can hand such objects to or receive them from CUDA-Python. For exampleThough there can be other valid ways to go