How cython memoryview accept input of various dimensions

140 views
Skip to first unread message

QINQIN KONG

unread,
Jan 8, 2021, 2:10:05 PM1/8/21
to cython-users
Hi everyone. I'm using cython to speed up my code, and use memoryview to let functions defined in cython accept array input. Eventually, I would like my function to be able to accept 3-D, 2-D, 1-D and even scalar input. However, it seems that I have to specify the dimension when I typed the memoryview of the arguments. Then how can I enable both 3-D, 2-D and 1-D input? One way I can imagine is define several functions doing the same thing but accepting input of different dimensions, and then write another caller function with a check of the input dimension to call specific processing function. But, is there any other more elegant way of doing this?

I got an answer from da-woods that: "the purpose of memoryviews is pretty much to enable fast indexing, so a memoryview with an unknown number of indexes isn't really a meaningful concept." If it can not be achieved by memoryviews, is there any other way around this while still using memoryviews to enable fast indexing?

Thanks a lot!

da-woods

unread,
Jan 8, 2021, 10:32:28 PM1/8/21
to cython...@googlegroups.com
What do you actually want to accomplish on these multi-dimensional memoryviews?

If you just want to perform a numeric operation on every element then you're probably better doing something like:

def implementation(double [:] x):
    # work does here

def wrapper(x):
   return implementation(np.asarray(x).ravel())

i.e. flatten the multidimensional array to a 1D array then operate element-by-element. If you're hoping to modify the array in place then you'll probably have to be a bit more careful with my example to avoid copying rather than passing references.

Another option would be to use a fused type:

cdef fused multiD:
    double
    double[:]
    double[:,:]
    double[:,:,:]

You may find it difficult to write a function that can meaningfully operate on such a type though (because what are you actually going to do with it that looks the same for all those different types?)

A further option would be to look at the C API of Numpy's nditer (which is what they use to work efficiently on arrays with different dimensionality). You'll find that quite complex though.
--

---
You received this message because you are subscribed to the Google Groups "cython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cython-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/cython-users/efc46984-551d-41ff-99be-791af656d93en%40googlegroups.com.


QINQIN KONG

unread,
Jan 9, 2021, 8:50:54 PM1/9/21
to cython-users
Thanks @da-woods. I'm writing a function to calculate a heat stress index and I want to publish it and so the community can use it. I personally, mainly use three dimensional (time*lat*lon) data as input such as the output from climate models (that's why I typed three dimensional memoryview in the cython function). But, I also want my code to be flexible and be able accept 2-D matrix or 1-D vectors since others may find this flexibility useful.
The flatten to 1-D approach may be not suitable since in my field (climate science), people often work with large arrays and the flatten and reshape may be too time or memory consuming? 

da-woods

unread,
Jan 10, 2021, 6:22:11 AM1/10/21
to cython...@googlegroups.com
Provided that the input array is contiguous then flatten and reshape do not require a copy and should be really, really fast.
Reply all
Reply to author
Forward
0 new messages