[Cython] [PATCH] make memoryviews work when strides is NULL (unfinished)
Christoph Groth
cwg at falma.de
Tue Sep 18 16:19:05 CEST 2012
Hi,
Thanks a lot for the recently added generic memoryview support, it's
just what we needed to optimize an important part of our program.
However, I believe that there's a problem with Cython's support for
objects which do not provide "strides" information (because they are
C-contiguous).
The buffer API documentation [1] is a bit ambiguous on this, but it says
"If strides is NULL, the array is interpreted as a standard
n-dimensional C-array."
In any case, numpy happily accepts such buffers and computes the
"strides" itself.
A thread [2] on Python's devel mailing list also supports the view that
setting strides to NULL is OK even if strides were requested.
You might ask: why not simply provide strides when they have been
requested? The problem is to find space for them. malloc'ing or
PyMem_Alloc'ing memory for strides each time when a buffer is requested
is slow, and reserving space for strides within the object is wasteful
when "shape" is all that's needed and you have _many_ small objects
which expose the buffer interface.
The provided patch works for our use case, but someone with a good
understanding of Cython's memoryview support should finish it. I
believe the patch will break more complicated buffer use cases.
[1] http://docs.python.org/dev/c-api/buffer.html
[2] http://thread.gmane.org/gmane.comp.python.devel/134387
Thank you for considering fixing this issue in Cython,
Christoph
---
Cython/Utility/MemoryView_C.c | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/Cython/Utility/MemoryView_C.c b/Cython/Utility/MemoryView_C.c
index 84e55da..c2524b0 100644
--- a/Cython/Utility/MemoryView_C.c
+++ b/Cython/Utility/MemoryView_C.c
@@ -207,12 +207,6 @@ static int __Pyx_ValidateAndInit_memviewslice(
goto fail;
}
- if (!buf->strides) {
- PyErr_SetString(PyExc_ValueError,
- "buffer does not supply strides necessary for memoryview.");
- goto fail;
- }
-
for(i=0; i<ndim; i++) {
spec = axes_specs[i];
@@ -320,8 +314,19 @@ __Pyx_init_memviewslice(struct __pyx_memoryview_obj *memview,
goto fail;
}
+ if (buf->strides) {
+ for (i = 0; i < ndim; i++) {
+ memviewslice->strides[i] = buf->strides[i];
+ }
+ } else {
+ Py_ssize_t stride = buf->itemsize;
+ for (i = ndim - 1; i >= 0; i--) {
+ memviewslice->strides[i] = stride;
+ stride *= buf->shape[i];
+ }
+ }
+
for (i = 0; i < ndim; i++) {
- memviewslice->strides[i] = buf->strides[i];
memviewslice->shape[i] = buf->shape[i];
if (buf->suboffsets) {
memviewslice->suboffsets[i] = buf->suboffsets[i];
--
1.7.10.4
More information about the cython-devel
mailing list