[SciPy-Dev] On pulling fwrap refactor into upstream SciPy
Dag Sverre Seljebotn
dagss at student.matnat.uio.no
Wed Feb 2 06:53:51 EST 2011
It's a good time to start a discussion on my Fwrap refactor of Fortran
wrappers in SciPy. I'd appreciate feedback from anyone who has an
opinion on whether the Fwrap refactor should be merged upstream and, if
so, how it should be done.
My SciPy branch is now feature complete without using f2py
(cblas/clapack missing and only numscons build, not distutils -- the
latter is definitely coming soon). What is there instead of f2py is
Cython files that call the Fortran code directly. The Cython code should
have the same API as f2py and be backwards compatible. The Cython files
were generated from the f2py pyf files by using Fwrap, but the generated
files were subsequently modified (rationale below) -- I've not really
been replacing f2py with Fwrap, it is more correct to say that I used
Fwrap to replace f2py with Cython.
My branch is here:
https://github.com/jasonmccampbell/scipy-refactor/tree/fwrap/
(Currently only numscons build is changed, not distutils. Also I didn't
check in generated C sources for now.)
I'll provide some more detailed information on specific
spots/differences once it's clear whether this is accepted upstream and
how review will be done. Overall:
* ABI: Same as f2py (Fortran 77 using the same blatant assumptions
that f2py did)
* Wrapper code typically looks like this:
https://github.com/jasonmccampbell/scipy-refactor/blob/fwrap/scipy/interpolate/dfitpack.pyx
In addition there's dfitpack_fc.h, dfitpack_fc.pxd which now expose the
raw Fortran ABI for use from C or Cython code.
* In the linalg package, there's pyx.in files, which are templates in
the Tempita language (http://pythonpaste.org/tempita/). E.g.:
https://github.com/jasonmccampbell/scipy-refactor/blob/fwrap/scipy/linalg/fblas.pyx.in
* Cython is more verbose, but also more explicit, than f2py. I also
think Cython is friendlier but I'm obviously biased. Two examples to
contrast the two:
i) "check(m > k)" in f2py code is done like this in Cython:
if not (m > k):
raise ValueError('Condition on arguments not satisfied: m > k')
So more verbose, but OTOH it is now trivial to modify the code to
provide a custom exception message, something impossible in f2py.
ii) Reordering the arguments in Cython is done by simply reordering the
arguments in the wrapper function. And custom code is simply inserted,
writing it in Cython. Whereas in f2py you get things like this:
callstatement {int
i=2*kl+ku+1;(*f2py_func)(&n,&kl,&ku,&nrhs,ab,&i,piv,b,&n,&info);for(i=0;i<n;--piv[i++]);}
callprotoargument
int*,int*,int*,int*,float*,int*,int*,float*,int*,int*
So, a (highly biased) summary: f2py code is much briefer for simple
things, but can get very hairy once one needs to do something
non-trivial. And the wrappers in SciPy often are non-trivial, there was
an incredible amount of "secret" tricks employed in the pyf files to
customize the wrappers that are now spelled out explicitly in Cython code.
However, the resulting code is more verbose, and perhaps more difficult
to quickly scan.
Dag Sverre
More information about the SciPy-Dev
mailing list