>> Also, in Numpy 1.6, arr.data and PyArray_DATA are equivalent (up to a
>> cast to the data type):
>> #define PyArray_DATA(obj) ((void *)(((PyArrayObject *)(obj))->data))
> That is due to change.
>> I think the best approach is for Cython to just translate arr.data into
>> PyArray_DATA(arr) in the generated C code.
>> It seems like there are shortcomings to all the major approaches:
>> * arr.data
>> o good: intent is clear (but the semantics don't actually >> match)
>> o bad: will break at some point, doesn't handle offsets >> properly
>> * &arr[0]
>> o good: intent is mostly clear, follows a common C++ idiom
>> o bad: requires completely disabling bounds checking for the
>> entire function to handle 0-length arrays
> No, it does not require bounds checking to be turned off. But it will > do a bounds check if you don't.
>> * PyArray_DATA(arr)
>> o good: has proper semantics
>> o bad: verbose and unpythonic
>> Would it make sense to enhance numpy.pxd to provide a new property
>> that acts like PyArray_DATA(arr) but looks pythonic (we might call
>> it zeroth_elem, first_elem, or something like that)?
> In my opinion we should use memoryviews instead, unless compatibility > with Python 2.4 is absolutely required. We are discussing how to use > an older, half-broken (useless for anything but trivial code), and > soon deprecated interface to solve a problem that memoryviews do right.
Anything but trivial functions will need slicing and function calls. You can see here how memoryviews allows us to code in "Fortran style" with arrays instead of using C style pointer arithmetics.
Pointer arithmetics is still not too bad in this simple case, but it can be much more complicated (but why bother?):
On Mon, Jul 30, 2012 at 1:37 PM, Sturla Molden <sturlamol...@yahoo.no> wrote:
> So I suggest one of these idioms for calling C from Cython:
> cdef double[:,::1] array = numpy_array
> cdef Py_ssize_t m, n
> m = array.shape[0]
> n = array.shape[1]
> foobar(m, n, &array[0,0])
> cdef view.array array = <double[:,::1]> numpy_array
> cdef Py_ssize_t m, n
> m = array.shape[0]
> n = array.shape[1]
> foobar(m, n, <double*> array.data)
The only difference is that first line: will they generate the same C
code? -- why would one choose on or the other?
(there should be one obvious way to do it...)
I'll probably go update the wiki page, but to make sure I'm clear:
Using a view.array will build a Cython "memoryview", using the
extended buffer interface -- so you can pass in any Python object that
supports PEP 3118 buffers (does anything other than numpy suport that
now??)
This is a lightweight way to both get a pointer to the data, and to
have a way, in Cython, to slice and dice the data.
Will this check for C-contiguous and raise an error if not?
-Chris
> Sturla
--
Christopher Barker, Ph.D.
Oceanographer
Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception
> On Mon, Jul 30, 2012 at 1:37 PM, Sturla Molden <sturlamol...@yahoo.no> wrote:
>> So I suggest one of these idioms for calling C from Cython:
>> cdef double[:,::1] array = numpy_array
>> cdef Py_ssize_t m, n
>> m = array.shape[0]
>> n = array.shape[1]
>> foobar(m, n, &array[0,0])
>> cdef view.array array = <double[:,::1]> numpy_array
>> cdef Py_ssize_t m, n
>> m = array.shape[0]
>> n = array.shape[1]
>> foobar(m, n, <double*> array.data)
> The only difference is that first line: will they generate the same C
> code? -- why would one choose on or the other?
> (there should be one obvious way to do it...)
> I'll probably go update the wiki page, but to make sure I'm clear:
> Using a view.array will build a Cython "memoryview", using the
> extended buffer interface -- so you can pass in any Python object that
> supports PEP 3118 buffers (does anything other than numpy suport that
> now??)
Not entirely. A cython.view.array is an array itself, that has memory
itself. In other words, it's a (lousy) replacement for numpy. It's
useful for users when they have memory allocated from somewhere and
want to turn it into a numpy array or memoryview. The array is more of
an intermediate thing, usually created implicitly by casting a
pointer: <double[:10:1, :10]> p creates a Fortran contiguous cython
array view on the memory of shape (10, 10).
> This is a lightweight way to both get a pointer to the data, and to
> have a way, in Cython, to slice and dice the data.
> Will this check for C-contiguous and raise an error if not?
Yes, buffers are always validated when they are assigned to by objects
at runtime. Assigning memoryviews to each other with wrong types is an
error, e.g.
>> cdef double[:,::1] array = numpy_array
>> cdef Py_ssize_t m, n
>> m = array.shape[0]
>> n = array.shape[1]
>> foobar(m, n, &array[0,0])
>> cdef view.array array = <double[:,::1]> numpy_array
>> cdef Py_ssize_t m, n
>> m = array.shape[0]
>> n = array.shape[1]
>> foobar(m, n, <double*> array.data)
> The only difference is that first line: will they generate the same C
> code? -- why would one choose on or the other?
The last line is also different ;-)
The first creates a typed memoryview of the NumPy array. That is, using the NumPy array as an PEP 3118 buffer directly from Cython. No auxillary Python object is created.
The second created an auxillary Cython array that shares memory with the NumPy array. The Cython array is a Python object with a PEP 3118 buffer. Unlike np.ndarray, it has a valid .data attribute that will not break.
If you dislike &array[0,0] syntax, pick the latter. If you don't want an auxillary Python object, pick the former.
> (there should be one obvious way to do it...)
> I'll probably go update the wiki page, but to make sure I'm clear:
> Using a view.array will build a Cython "memoryview", using the
> extended buffer interface -- so you can pass in any Python object that
> supports PEP 3118 buffers (does anything other than numpy suport that
> now??)
Typed memoryviews will give you convinient and fast data access and fast array slicing in Cython. cython.view.array can e.g. be used if you need to send a C pointer as a Python pep 3118 object to some Python routine.
Thus they are not exactly the same, but "almost".
Typical use cases:
double[:,:] or double[:,::1]:
- You have a C pointer, you want fast "NumPy style" indexing and slicing.
- You have a NumPy array, you want fast indexing and fast slicing.
- You are considering to use Fortran because of its array syntax.
double[::1,:]:
- You need to interface with Fortran code.
- You are porting old Fortran code line-by-line.
- You are working with OpenGL.
cython.view.array:
- You have a C pointer and need a Python PEP 3118 object.
- You want a safe replacement for malloc (one that is faster than NumPy).
- You are porting old NumPy/Cython code that uses the .data attribute everywhere.
Also beware of this:
Common contra-indications for using double[::1,:] orcython.view.array:
- You need to interface with BLAS. Use cblas instead.
- You need to interface with LAPACK. Use LAPACKE instead.
- You need to allocate WORK arrays for LAPACK. Use LAPACKE instead.
>>> cdef double[:,::1] array = numpy_array
>>> cdef Py_ssize_t m, n
>>> m = array.shape[0]
>>> n = array.shape[1]
>>> foobar(m, n, &array[0,0])
>>> cdef view.array array = <double[:,::1]> numpy_array
>>> cdef Py_ssize_t m, n
>>> m = array.shape[0]
>>> n = array.shape[1]
>>> foobar(m, n, <double*> array.data)
> The first creates a typed memoryview of the NumPy array. That is, using the
> NumPy array as an PEP 3118 buffer directly from Cython. No auxillary Python
> object is created.
OK -- the original start of this post was how best to essentially pass
though a numpy data buffer to C/C++ code (or Fortran, I suppose).
So it looks like:
cdef double[:,::1] array = numpy_array
is very lightweight, so may be a good way to go, and would support
other PEP 3118 buffer objects, so seems a good idea.
> The second created an auxillary Cython array that shares memory with the
> NumPy array. The Cython array is a Python object with a PEP 3118 buffer.
> Unlike np.ndarray, it has a valid .data attribute that will not break.
> If you dislike &array[0,0] syntax, pick the latter. If you don't want an
> auxillary Python object, pick the former.
>> (there should be one obvious way to do it...)
>> I'll probably go update the wiki page, but to make sure I'm clear:
>> Using a view.array will build a Cython "memoryview", using the
>> extended buffer interface -- so you can pass in any Python object that
>> supports PEP 3118 buffers (does anything other than numpy suport that
>> now??)
> Typed memoryviews will give you convinient and fast data access and fast
> array slicing in Cython. cython.view.array can e.g. be used if you need to
> send a C pointer as a Python pep 3118 object to some Python routine.
> Thus they are not exactly the same, but "almost".
> Typical use cases:
> double[:,:] or double[:,::1]:
> - You have a C pointer, you want fast "NumPy style" indexing and slicing.
> - You have a NumPy array, you want fast indexing and fast slicing.
> - You are considering to use Fortran because of its array syntax.
> double[::1,:]:
> - You need to interface with Fortran code.
> - You are porting old Fortran code line-by-line.
> - You are working with OpenGL.
> cython.view.array:
> - You have a C pointer and need a Python PEP 3118 object.
> - You want a safe replacement for malloc (one that is faster than NumPy).
> - You are porting old NumPy/Cython code that uses the .data attribute
> everywhere.
> Also beware of this:
> Common contra-indications for using double[::1,:] orcython.view.array:
> - You need to interface with BLAS. Use cblas instead.
> - You need to interface with LAPACK. Use LAPACKE instead.
> - You need to allocate WORK arrays for LAPACK. Use LAPACKE instead.
> Sturla
--
Christopher Barker, Ph.D.
Oceanographer
Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception
> This is because you are not importing cython. After adding "cimport cython",
sorry about that -- I"ve updated the wiki -- I thought I cut&pasted
from a working version...
> next error is in generating "multiply.c" file.
> multiply.o:multiply.c:(.text+0x5c3): undefined reference to
> `_imp__c_multiply'
> Any pointers? I am not much into cython lust started digging.
try the latest Cython -- then report back.
-Chris
--
Christopher Barker, Ph.D.
Oceanographer
Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception
running build_ext cythoning multiply.pyx to multiply.c building 'multiply' extension D:\MinGW\bin\gcc.exe -mno-cygwin -mdll -O -Wall -IC:\Python26\lib\site-packages\numpy\core\include -IC:\Python26\include -IC:\Python26\PC -c multiply.c -o build\temp.win32-2.6\Release\multiply.o multiply.c: In function `__Pyx_GetBuffer': multiply.c:4353: warning: unused variable `getbuffer_cobj' multiply.c: In function `__Pyx_ReleaseBuffer': multiply.c:4393: warning: unused variable `releasebuffer_cobj' multiply.c: At top level: C:/Python26/lib/site-packages/numpy/core/include/numpy/__multiarray_api.h:1 533: warning: '_import_array' defined but not used C:/Python26/lib/site-packages/numpy/core/include/numpy/__ufunc_api.h:227: warning: '_import_umath' defined but not used D:\MinGW\bin\gcc.exe -mno-cygwin -mdll -O -Wall -IC:\Python26\lib\site-packages\numpy\core\include -IC:\Python26\include -IC:\Python26\PC -c c_multiply.c -o build\temp.win32-2.6\Release\c_multiply.o c_multiply.c:22:2: warning: no newline at end of file writing build\temp.win32-2.6\Release\multiply.def D:\MinGW\bin\gcc.exe -mno-cygwin -shared -s build\temp.win32-2.6\Release\multiply.o build\temp.win32-2.6\Release\c_multiply.o build\temp.win32-2.6\Release\multiply.def -LC:\Python26\libs -LC:\Python26\PCbuild -lpython26 -lmsvcr90 -o D:\Projects\cython\multiply.pyd build\temp.win32-2.6\Release\multiply.o:multiply.c:(.text+0x6ff): undefined reference to `_imp__c_multiply' collect2: ld returned 1 exit status error: command 'gcc' failed with exit status 1
On Fri, Aug 24, 2012 at 10:26 PM, Prashant <animator...@gmail.com> wrote:
> This is with cython 0.16
> running build_ext
> cythoning multiply.pyx to multiply.c
> building 'multiply' extension
> D:\MinGW\bin\gcc.exe -mno-cygwin -mdll -O -Wall
> -IC:\Python26\lib\site-packages\numpy\core\include -IC:\Python26\include
> -IC:\Python26\PC -c multiply.c -o build\temp.win32-2.6\Release\multiply.o
> multiply.c: In function `__Pyx_GetBuffer':
> multiply.c:4353: warning: unused variable `getbuffer_cobj'
> multiply.c: In function `__Pyx_ReleaseBuffer':
> multiply.c:4393: warning: unused variable `releasebuffer_cobj'
> multiply.c: At top level:
> C:/Python26/lib/site-packages/numpy/core/include/numpy/__multiarray_api.h:1 533:
> warning: '_import_array' defined but not used
> C:/Python26/lib/site-packages/numpy/core/include/numpy/__ufunc_api.h:227:
> warning: '_import_umath' defined but not used
> D:\MinGW\bin\gcc.exe -mno-cygwin -mdll -O -Wall
> -IC:\Python26\lib\site-packages\numpy\core\include -IC:\Python26\include
> -IC:\Python26\PC -c c_multiply.c -o
> build\temp.win32-2.6\Release\c_multiply.o
> c_multiply.c:22:2: warning: no newline at end of file
> writing build\temp.win32-2.6\Release\multiply.def
> D:\MinGW\bin\gcc.exe -mno-cygwin -shared -s
> build\temp.win32-2.6\Release\multiply.o
> build\temp.win32-2.6\Release\c_multiply.o
> build\temp.win32-2.6\Release\multiply.def -LC:\Python26\libs
> -LC:\Python26\PCbuild -lpython26 -lmsvcr90 -o
> D:\Projects\cython\multiply.pyd
> build\temp.win32-2.6\Release\multiply.o:multiply.c:(.text+0x6ff): undefined
> reference to `_imp__c_multiply'
> collect2: ld returned 1 exit status
> error: command 'gcc' failed with exit status 1
--
Christopher Barker, Ph.D.
Oceanographer
Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception