[ENH] Auto-generation of ufuncs
See original GitHub issueIs your feature request related to a problem? Please describe.
The Numpy C API defines a way to generate “ufuncs” from a C function pointer. The C API takes a C callable and converts it into a Python callable that works on arrays of varying dimensions (broadcasting), and also handles reductions and broadcasting I think.
Describe the solution you’d like
The Numpy C API for this is accessible in Cython (via the pxd files) but is not hugely intuitive. It is also based around void*
s to access the data, rather than the nicer Cython types like typed memoryviews). Therefore it might be nice to have a decorator to convert Cython cdef functions into Numpy ufuncs to allow them to work well with array broadcasting (people sometimes try to solve this problem with fused types of double[:]
, double[:,:]
, double[:,:,:]` etc., which is OK, but a bit ugly).
Example code:
cimport cython
@cython.numpy_ufunc
cdef double add(double x, double y):
return x+y # obviously a trivial example which is in Numpy already
Additional context
Numba provides a similar feature https://numba.pydata.org/numba-doc/dev/user/vectorize.html, so there’s precedent (and people would probably understand it)
The Numpy C API also provides “generalised ufuncs”. These would also be nice, but probably not part of an initial implementation.
This’d introduce a runtime+compile-time dependency on Numpy. Cython typically tries to be fairly dependency-free by default. I’ve proposed the decorator name numpy_ufunc
to try to make that dependency as clear as possible. There’s also a question: is there a way to do this without tying it to Numpy.
In the more distant future this might be a good place to introduce other backends (e.g. gpu, parallelization?). But definitely not for the initial version.
I have no immediate plans to implement this for the moment - posted mainly to get a bit of feedback about whether it’s likely to be useful
Issue Analytics
- State:
- Created a year ago
- Reactions:3
- Comments:5 (1 by maintainers)
Top GitHub Comments
This would be great to have! I played around with a
ufunc
-cython
integration a bit here because I needed to evaluate the likelihood of a distribution repeatedly. But the interface in the linked repo is still pretty clunky. See here for the application.@gwerbin Check out my PR, go to this line (https://github.com/cython/cython/blob/c7ba0c83d7fa7c0db60742b117b9e0207493013f/Cython/Compiler/UFuncs.py#L156) and add
print(code.impl)
and that should show the generated utility code I hope.Note that the one thing that doesn’t work in multiple return types where one of the types is a PyObject. That’s really a consequence of the syntax I’ve used than a fundamental block.
There’s also a small amount of C utility code. Think that all could be written in Cython but isn’t (mainly for convenience). I think you’d add
print(TempitaUtilityCode.load("UFuncConsts", "UFuncs_C.c", context=context).impl)
(near https://github.com/cython/cython/blob/c7ba0c83d7fa7c0db60742b117b9e0207493013f/Cython/Compiler/UFuncs.py#L230) to see that.