[Numpy-discussion] Misc Pyrex questions

Francesc Altet faltet at carabos.com
Tue Jan 23 14:35:32 EST 2007


Oops, the attachments! (always the same history)

El dt 23 de 01 del 2007 a les 20:33 +0100, en/na Francesc Altet va
escriure:
> El 2007-01-22 23:59:03 GMT, en/na Pierre GM va escriure:
> > Other example: what's more efficient ? 
> > myvar = <ndarray>numpy.empty(shape,dtype)
> > or
> > myvar = PyArray_EMPTY(dims, NPY_TYPE)
> 
> Ok. The second one indeed, but possibly less than you realize (just a
> 25%, see some benchmarks below). The main point is, as always, avoiding
> premature optimization. You should first port your code to Pyrex, and
> then concentrate on the hot points. If some python calls are critical
> for you, then, go ahead and choose the C call.
> 
> > But elsewhere in the manual is given the example of a loop using `range`, when 
> > one should use some explicit interval, and my understanding was that using 
> > python expressions was not as efficient as having more proper C expressions. 
> > Is this the case here ? Do I have to reimplement __getitem__ on arrays, or 
> > could I just keep on using the current approach ?
> 
> Special methods (like __getitem__) of Pyrex extensions performs exactly
> the same than a __getitem__ made in pure C extensions. So, you don't
> have be worried about that.
> 
> A benchmark that I've made (I was curious too ;), and that I'm
> attaching, proves this. Here is the run on a pretty old machine:
> 
> $ python run_bench.py
> ******************** NumPy times *********************************
> time for __len__ (numpy)--> 0.203
> sum (numpy)--> 49987.2991813
> time for __getitem__ (numpy)--> 0.314
> ******************** Pyrex times *********************************
> time for __len__ (pyrex)--> 0.198
> sum (pyrex)--> 49987.2991813
> time for __getitem__ (pyrex)--> 0.172
> ********* Comparing NumPy creation times (python and C) **********
> time for creating an empty array (python)--> 3.305
> time for creating an empty array (C)--> 2.664
> 
> In this case, the __getitem__ of Pyrex seems to perform better than the
> __getitem__ of the ndarray object written in C (almost a 2x, in fact).
> However, this is probably an ilusion, as the ndarray __getitem__ will do
> far more work than the Pyrex one. OTOH, the __len__ method is far more
> simple, and can be taken as the demonstration that the overhead of
> calling special methods in Pyrex from Python is similar to C
> counterparts. Finally, the difference of overhead in using a Python or a
> C call for creating an empty array is shown in the last part of the
> benchmark. All in all, a 25% of difference is not that much.
> 
> Cheers,
> 
-- 
Francesc Altet    |  Be careful about using the following code --
Carabos Coop. V.  |  I've only proven that it works, 
www.carabos.com   |  I haven't tested it. -- Donald Knuth
-------------- next part --------------
"""Here are some definitions for sharing between extensions.

"""

# Standard C functions.
cdef extern from "stdlib.h":
  ctypedef long size_t
  void *malloc(size_t size)
  void free(void *ptr)

# API for NumPy objects
cdef extern from "numpy/arrayobject.h":

  # Types
  ctypedef int npy_intp

  # Functions
  object PyArray_GETITEM(object arr, void *itemptr)
  int PyArray_SETITEM(object arr, void *itemptr, object obj)
  object PyArray_EMPTY(int m, npy_intp *dims, int type, int fortran)

  # Classes
  ctypedef extern class numpy.dtype [object PyArray_Descr]:
    cdef int type_num, elsize, alignment
    cdef char type, kind, byteorder, hasobject
    cdef object fields, typeobj

  ctypedef extern class numpy.ndarray [object PyArrayObject]:
    cdef char *data
    cdef int nd
    cdef npy_intp *dimensions
    cdef npy_intp *strides
    cdef object base
    cdef dtype descr
    cdef int flags

  # The NumPy initialization funtion
  void import_array()


-------------- next part --------------
A non-text attachment was scrubbed...
Name: Makefile
Type: text/x-makefile
Size: 129 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/numpy-discussion/attachments/20070123/5967ca19/attachment.bin>
-------------- next part --------------
definitions.pxd
pyrex_bench.pyx
run_bench.py
setup.py
-------------- next part --------------
import numpy

from definitions cimport import_array, \
     malloc, free, npy_intp, \
     PyArray_GETITEM, PyArray_EMPTY, \
     ndarray, dtype

# NumPy must be initialized
import_array()


#######################################################################
# Bench for calling special methods
#######################################################################

cdef class myarray:
  """Class that implements some added features from a ndarray object.
  """
  cdef long nslots
  cdef npy_intp stride
  cdef void *mydata
  cdef ndarray myarray

  def __init__(self, nparray):
    self.nslots = len(nparray)
    self.myarray = <ndarray>nparray
    self.mydata = <void *>self.myarray.data
    self.stride = self.myarray.strides[0]

  def __len__(self):
    return self.nslots

  def __getitem__(self, long key):
    cdef long offset

    offset = <long>(key * self.stride)
    return PyArray_GETITEM(self.myarray, self.mydata + offset)


########################################################################
# Bench for creating NumPy objects
########################################################################

def empty1(shape, dtype_, niter):
  cdef int i
  cdef ndarray myarray
  
  for i from 0 <= i < niter:
    myarray = <ndarray>numpy.empty(shape, dtype_)

def empty2(shape, dtype dtype_, niter):
  cdef int i, m, npy_type
  cdef npy_intp *dims
  cdef ndarray myarray

  npy_type = dtype_.type_num
  m = len(shape)
  dims = <npy_intp *>malloc(m * sizeof(npy_type))
  for i from 0 <= i < m:
    dims[i] = shape[i]
  for i from 0 <= i < niter:
    myarray = PyArray_EMPTY(m, dims, npy_type, 0)
  free(<void *>dims)

## Local Variables:
## mode: python
## py-indent-offset: 2
## tab-width: 2
## fill-column: 78
## End:
-------------- next part --------------
A non-text attachment was scrubbed...
Name: run_bench.py
Type: text/x-python
Size: 1164 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/numpy-discussion/attachments/20070123/5967ca19/attachment.py>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: setup.py
Type: text/x-python
Size: 565 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/numpy-discussion/attachments/20070123/5967ca19/attachment-0001.py>


More information about the NumPy-Discussion mailing list