Search code examples
pythonfortrancythoncontiguous

Making a memoryview C-contiguous Fortran-contiguous


I am using C-contiguous memoryviews in my Python code and I would like to use dgemm which needs Fortran-contiguous memoryviews. I would like to use the function PyMemoryView_GetContiguous found here but I don't know how to access it.

Does someone know which import I have to do ?

I don't want to use the function copy_fortran() as it really slows down my code.


Solution

  • PyMemoryView_GetContiguous doesn't look to be exposed as part of the Cython standard includes unfortunately. It should be reasonably easy to wrap though:

    from cpython.buffer cimport PyBUF_READ # we'll need this later
    
    cdef extern from "Python.h":
        # copy the signature replacing PyObject* with object to let Cython
        # handle the reference counting
        object PyMemoryView_GetContiguous(object, int, char)
    
    def test(double[:,::1] c_contig):
       f_contig = PyMemoryView_GetContiguous(c_contig, PyBuf_READ,'F')
       # .... do something useful
    

    Be aware that this will still involve copying all the memory (this is absolutely unavoidable!) so is unlikely to be significantly faster than copy_fortran.


    There's a problem though - PyMemoryView_GetContiguous won't return a writeable memoryview unless it does not have to make a copy, and Cython requires things assigned to a typed memoryview be writeable, so you can only use it as a Python object.

    You can get a pointer to the first element though - the underlying object that created is a bytes/str object, so you can get a char* then cast that to whatever pointer you need. This should be enough to call your Fortran functions:

    cdef char* as_bytes = f_contig.obj
    some_function(<double*>as_bytes)