On May 18, 2010, at 2:55 PM, jah wrote:

> Long post, but I hoped to be thorough.
>
> I'm having some trouble generalizing a simple Cython implementation  
> that made feasible a previously infeasible Python implementation.   
> The problem can be cast as follows:
>
>   Let f(x,p) be a function, for example f(x,p) = sin(p*x).
>   Pick a range of values for p, call this: pvalues
>   Then, in pseudocode:
>
>      for p in pvalues:
>         xn = x0
>         for i in range(n):
>             # this could benefit from ticket #474
>             xn = f(xn, p)
>             # increment count for bin at (xn, p)
>             # ...
>     return bincounts
>
> I'm following the technique in the Cython tutorial that was written  
> for Scipy 2009, and I have the following extension class defined:
>
> ctypedef np.float_t FTYPE_t
> cdef class MyFunction:
>     cpdef FTYPE_t evaluate(self, FTYPE_t x)
>
> This gives me the flexibility to define the function in Python space  
> as well (which is desirable). So I've coded this function as above,  
> making sure to provide types for everything, with the following call  
> signature:
>
> @cython.boundscheck(False)
> @cython.wraparound(False)
> def histogram(MyFunction func not None,
>               np.ndarray[FTYPE_t, ndim=1] pvalues,
>               FTYPE_t x0,
>               int n,
>               int bins):
>
> Then the fundamental line which exists in the inner loop is:
>
>    xn = func.evaluate(xn, p)
>
> Everything works and is quick. Now, I'm having trouble generalising  
> this so that both x and p can be vectors of arbitrary (but fixed)  
> length. My understanding says that I must go from cpdef to just def  
> (due to ticket #177):
>
> ctypedef np.float_t FTYPE_t
> cdef class MyFunction:
>     def evaluate(self, np.ndarray[FTYPE_t, ndim=1, mode="c"] x,
>                        np.ndarray[FTYPE_t, ndim=1, mode="c"] p):
>
> Of course, the problem now is that I have making a Python call  
> inside a doubly nested forloop and things get much slower.  I can  
> see that p would be fixed in the inner loop, but I'd still have to  
> deal with the fact that xn is changing each time.
>
> So how can I implement this quickly and generally? Thanks!

One of the justifications (meaning we'd like to fix this, but it's  
been lower priority than other stuff) for only implementing buffer  
types in def (rather than cdef) calls is that usually if you're  
passing a whole array into a function, the relative overhead of  
calling the function is less significant compared to what's going on  
inside. Of course, this is not always the case. Is your evaluate  
really fast compared to the overhead of a Python function call?

- Robert

_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev

Reply via email to