Skip to content

ENH: Cython interface for special #6195

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Jul 21, 2016
Merged

ENH: Cython interface for special #6195

merged 19 commits into from
Jul 21, 2016

Conversation

person142
Copy link
Member

@person142 person142 commented May 28, 2016

This defines typed, scalar versions of many of the functions in
scipy.special and makes them available to cimport in Cython. It uses
fused types so that the functions have the same names and signatures
as their ufunc counterparts.

It piggybacks off of the existing code generation in
generate_ufuncs.py. In particular:

  • The process for adding new ufuncs is unchanged
  • When a new ufunc is added a Cython version will automatically be
    created (subject to some restrictions mentioned at the end), and the
    documentation and tests will be automatically updated.

This does not attempt to add Cython versions of:

  • Ufuncs with multiple return arguments Ufuncs with multiple return arguments are now supported
  • Ufuncs that have additional layers of python wrappers.

With more work these restrictions could be removed.

Closes gh-5964.

@rgommers rgommers added enhancement A new feature or improvement scipy.special labels May 29, 2016
@rgommers
Copy link
Member

rgommers commented Jun 5, 2016

This looks quite promising @person142!

There are 2 test failures for the latest commit, those are real.

@rgommers
Copy link
Member

rgommers commented Jun 5, 2016

Benchmarks are quite consistent; numpy and cython same speed (except ~400ns less overhead for small arrays with cython), Python significantly slower:

[ 57.14%] ··· Running cython_special.CythonSpecial.time_gamma_d                                      ok
[ 57.14%] ···· 
               ========== ====== ========== ========== ==========
               --                              api               
               ----------------- --------------------------------
                argument    N      python     numpy      cython  
               ========== ====== ========== ========== ==========
                 (100,)     10    10.61μs     2.11μs     1.59μs  
                 (100,)    100    95.18μs    12.64μs    12.19μs  
                 (100,)    1000   890.96μs   122.49μs   117.66μs 
               ========== ====== ========== ========== ==========

And autogenerating benchmarks is a nice touch.

@person142
Copy link
Member Author

Yes, I need to track those failures down. I ran into an issue before that became gh-6208; might be more of the same.

I have noticed one circumstance where cython is slower than numpy, and that's functions with a lot of complex arguments and an underlying c function that's using numpy cdoubles (e.g. the airy benchmark). I guess the extra time is coming from all the casting back and forth between double complex and cdouble.

@pv
Copy link
Member

pv commented Jun 5, 2016

It would be surprising if the time difference comes from casting, since that should not be very many cpu cycles, compared to the floating point math the function in the end does.

@person142
Copy link
Member Author

I looked at the generated cython wrappers for pro_rad2 and pro_rad2_cv and didn't see anything suspicious, and while gh-6211 doesn't specifically address the test failures it makes me suspect the underlying issue is in specfun.f. (Uninitialized memory getting accessed and making the outputs nondeterministic.)

I marked the radial spheroidal wave functions as known failures; if people are not happy with this I'll dig deeper into the Fortran code and try to pinpoint the error.

@rgommers
Copy link
Member

@person142 it would be good to advertise this PR on the mailing list. I'm sure some people will be interested.

@rgommers
Copy link
Member

I marked the radial spheroidal wave functions as known failures; if people are not happy with this I'll dig deeper into the Fortran code and try to pinpoint the error.

Addressing that separately is ok I think.

Cython API for Special Functions
================================

Scalar, typed versions of many of the functions in ``scipy.special``
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be simpler to just list all the available C signatures, rather than the internal representation used in generate.py --- this way it would be more self-explanatory.

@person142
Copy link
Member Author

@ev-br
Copy link
Member

ev-br commented Jun 17, 2016

While I won't be able to review the details, I played a bit with this from a user perspective and it looks great. Don't know if this makes this release or the next one, but this definitely should be a highlight of a release.

One longer-term question, not for this PR. Would it be possible to add some magic to dispatch to these functions automatically when a special function is called with scalar arguments?

@@ -77,7 +77,7 @@ npy_cdouble clngamma_wrap( npy_cdouble z) {

npy_cdouble chyp2f1_wrap( double a, double b, double c, npy_cdouble z) {
npy_cdouble outz;
int l1, l0;
int l1, l0, isfer;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initialize isfer = 0 --- since it's not set by the fortran routine always, the result is undefined.

@pv pv mentioned this pull request Jun 18, 2016
@pv
Copy link
Member

pv commented Jun 18, 2016

Ok, a few comments:

  • I think autogeneration for tests and benchmarks is a bit too far --- I'd write these manually.
  • The test_cython_special api tests don't seem to pick the function with correct signatures (as noted above, the _float et al map to Python floats, so you always check a single specialization).

I have fixes for the above in my branch, cf person142/scipy@cython-interface...pv:pr-6195

@pv
Copy link
Member

pv commented Jun 18, 2016

Apart from that, looks great to me.

@pv pv added the needs-work Items that are pending response from the author label Jun 18, 2016
@person142
Copy link
Member Author

Thanks for the fixes @pv. I moved the known failure check to earlier in the test so that those functions never get evaluated. I've had pbwa cause a segfault before.

@pv pv removed the needs-work Items that are pending response from the author label Jun 18, 2016
@pv
Copy link
Member

pv commented Jun 18, 2016

Other stuff: cython_special.pxd doesn't get installed, missing from setup.py

@person142
Copy link
Member Author

I think I fixed it.

This defines typed, scalar versions of many of the functions in
scipy.special and makes them available to cimport in Cython. It uses
fused types so that the functions have the same names and signatures
as their ufunc counterparts.

It piggybacks off of the existing code generation in
generate_ufuncs.py. In particular:

- The process for adding new ufuncs is unchanged
- When a new ufunc is added a Cython version will automatically be
  created (subject to some restrictions mentioned at the end), and the
  documentation and tests will be automatically updated.

This does not attempt to add Cython versions of:

- Ufuncs with multiple return arguments
- Ufuncs that have additional layers of python wrappers.

With more work these restrictions could be removed.

Closes scipygh-5964.
This mimics the behavior of iter_varaints in generate_ufuncs.py
Hopefully this will fix issues with conversions.
Modifies specfun.f to return sf_error codes in added flag variables
instead of printing warnings. The error codes are caught by the c
wrapper functions and the appropriate sf_error is raised.

This silences a lot of noise in test_cython_special.py.
Also make generate_ufuncs.py automatically generate the benchmarks.
@person142
Copy link
Member Author

And rebased.

@pv pv added this to the 0.19.0 milestone Jul 21, 2016
@pv pv merged commit 0a03211 into scipy:master Jul 21, 2016
@pv
Copy link
Member

pv commented Jul 21, 2016

Thanks, merged based on positive feedback.

@person142
Copy link
Member Author

Thanks for taking the time to review @pv.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement A new feature or improvement scipy.special
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants