-
-
Notifications
You must be signed in to change notification settings - Fork 5.1k
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
Faster expm #354
Faster expm #354
Conversation
Thanks. We might also want to wrap the expokit Krylov routines for supporting sparse and matrix-free operators. |
Yes, scipy.linalg.expm also supports sparse matrices, so not supporting them would be a regression. I tried to wrap the matrix-free Krylov routines (dgexpv and zgexpv), in order to support sparse matrices, but as mentioned above, I couldn't get consistent results with the native SciPy functions. My testing procedure was as follows:-
|
It's also worth mentioning that there is an API difference between expowrap.expm(A, t=None) and scipy.linalg.expm(A, q=None). When I used it, I needed to specify the time, t with which to multiply the matrix before exponentiating it. i.e. exp(A*t). This functionality is not available within SciPy's expm function, but I've left it in the expokit wrapper, as I think it could be valuable to others too. If left unspecified, the signature file says to use t=1., by default. |
@rgommers can this go into 0.12? |
It's a very good start, but not ready to merge just yet:
|
Sorry to have left it in this state! It's really below par compared with the rest of SciPy. I was stumped trying to fix the sparse routines and, having no actual need to use them myself, had to divert my attention elsewhere before tidying the rest of it. I do have some thoughts to add, though:
|
I think we want to have the routine on top level of OTOH, we already have I think it would be good to understand the precision issues before merging this PR, or at least have certainty that the wrapper is working as expected. It's also possible Scipy's current expm routines aren't as accurate, although Higham's Pade approximants should in principle be good. The more problems that are addressed now as opposed to later, the better --- there have been several examples in Scipy on what happens if you leave things for "later"... I think support for sparse matrices would be nice, but that can be left also for later. Expokit's routines here take a matvec function, so one needs to tell f2py to have a callback function. The Python side should be written so that any The present version looks already quite good, but it needs some polish (+ the precision issue). |
@pv Only 3? Still 16 expm functions to go: http://www.cs.cornell.edu/cv/researchpdf/19ways+.pdf . I really think the ability to provide t as an expm argument would be great in scipy, but sadly my knowledge in wrapping fortran code is not existent, so i cant help. For precession issues, i would probably believe expokit more than scipy. |
So was mine 'til I needed expm. numpy's f2py makes it amazingly simple though! Just seen a nice-looking tutorial here: http://websrv.cs.umt.edu/isis/index.php/F2py_example To clarify, the .pyf wrappers in the commit were automatically generated with f2py. I manually edited the wrappers for a couple of the routines, listed as "IMPLEMENTED", and the "unimplemented" ones should I think be brought up to a similar standard of automatic argument generation and then of course tested... |
What is the status of this --- is it superseded by gh-2441 and further activity, or is there something left here? |
It's not clear if EXPOKIT is more effective than the Higham algorithms @argriffing implemented. We could add a AFAIK, the feature set of the Krylov expm approximants in EXPOKIT are also covered by the Al-Mohy&Higham algorithm implemented in expm_multiply. I'd need to reread the expokit docs to be more sure if there's something missing. |
I think this subset is already covered in scipy, between |
I haven't tested this code since the new expm was introduced and I couldn't comment on its accuracy, but I did find EXPOKIT's dgpadm quite a bit faster than SciPy's I don't have my working copy checked out atm, so can't really be much more more help I'm afraid (for the next couple of weeks, at least). Maybe it would be a good idea to add a module to benchmark the different implementations. Just had a look and perhaps |
Just had a little play with the code and tidied it up somewhat, as per above suggestions by @pv. Thought people might like to see some benchmark results, so here they are, for dense, square matrices up to 50x50 in size:
I remember now that run-time ratios converge as the matrices get larger, but expokit seems to always have a slight lead. I used 200x200 matrices in practice, so if that's a likely use-case:
This was compiled with Intel Compilers, linked against threaded MKL and run on a 6-core Intel CPU with HT (Intel W3680 @ 3.33GHz). There are still precision differences, but I couldn't comment on the reasons for that, whether the algorithm or some parameter given to it. I've tried to make Will push my changes over now... |
…name expowrap.py to expokit.py, providing public interface. Turn time_expm.py into a proper benchmark module (with unittests), and removed redundancy between time_expm.py and expowrap.py (now linalg.benchmarks.bench_expm and linalg.expokit). Sparse matrices still not working...
@alexleach: which version of Scipy did you use for the benchmarks? Note that there have been quite big changes in Scipy expm routines recently. |
@pv: Yes, good point! The benchmark results are only from my fork, which is about 7 months old by the look of it.. I've got release 0.12.0 installed as well. I'll see how that compares.. |
Against 0.12.0 release:
The compile flags may have been slightly different, but both were buit and linked against the same versions of icc, ifort and MKL. Runtime setup:-
Absolute imports (of |
I'd like to investigate this in more detail, but I'll be unavailable for the next couple weeks. Here are some of my thoughts on expm before I leave. In any case, thanks for your work to look at putting EXPOKIT into scipy!
|
I just updated my working copy to scipy master, merged my changes and created a gist report containing the full output of See https://gist.github.com/alexleach/5e8a38d4e8bb90f4a53f Would it make a huge mess of this PR if I updated my github fork to scipy's HEAD? Only one (minor) merge was necessary, in @argriffing Licensing was discussed on the scipy-user mailing list. I did request and receive permission from the Expokit author; his full response is at: http://mail.scipy.org/pipermail/scipy-user/2012-November/033600.html Thanks for linking those benchmarks and tests; I hadn't spotted them before. I might get a chance to implement test them out in a few weeks, but I'll have to leave this alone for the time being... |
To quickly check which is more accurate, maybe use something like expm(logm(rand())) and see which roundtrip causes less difference? This isn't perfect because it depends on logm accuracy. |
I ran 1,000 iterations of single random numbers and 1,000 runs with random 2x2 arrays, with slightly inconsistent results. I put up the code I ran at https://gist.github.com/alexleach/4814fa84089ba67accb8 as a fairly minimal working example. Results over a run of 1,000 iterations:
|
Even if this scipy EXPOKIT wrapper would not immediately replace
I'm not good with git. The preferred way to do PRs is to make your own branch per PR instead of making changes to the master branch in your fork, and I'm not sure what is the best way to recover. If some version of this expokit wrapper would be merged into scipy master then I might do some more testing and benchmarking, but I'm not up for "cherry picking" or whatever would be required otherwise. |
@pv how would this fortran interact with your fortran-splitting work? In particular I'm thinking about how to modify the scipy/linalg/setup.py file. I basically don't know anything about fortran or about the scipy build process. |
Perhaps fortran errors like https://github.com/alexleach/scipy/blob/1769fdd06b8b1348656bd2a60b7c2c62ad1ed9fa/scipy/linalg/src/expokit.f#L508 should be turned into scipy errors somehow, or maybe there is already a way to do this. The fortran |
@argriffing: the "fortran-splitting" was just a work-around needed by |
@alexleach here's a PR where I've played around with your expokit wrapper #2974. It features more integration into scipy, adds some new tests, and currently does not have merge conflicts. |
Arbitrary precision matrix exponential seems to have been implemented here: |
is this stalled? |
@auvipy Yes it's stalled as of two and a half years ago. Some features related to this PR are now available in scipy, but I'm pretty sure that some functions in expokit are better in some ways than the analogous functions that are currently in scipy. |
Some other functions zhexpv, dsexpv are also very useful, which may be lacking in the scipy.scipy.linalg.expm_multiply. According to the doc of expokit, these two functions which take Besides, the expm_multiply function lacks a 'tol' argument. |
Hi,
As per the discussions on the Scipy-Dev and Scipy-User mailing lists, I've implemented a couple of the EXPOKIT Fortran routines, as an alternative for scipy.linalg.expm.
Merging this into SciPy is still work in progress, but I hope someone can pick up where I left off, and fully integrate this into SciPy.
Work I think is left to be done:-
And probably some other things...
There are Chebyshev routines in Expokit, which might provide speed improvements cf. the SciPy Chebyshev functions, but I haven't needed to use them, so haven't used or done anything with them. Some of these are used internally by the sparse matrix functions.
The signature file contains auto-generated signatures for all the functions in Expokit, including the ones I didn't use or modify wrappers for, too. It's probably safe to delete the signatures for these.
The only routines I think need to be accessible from Python, for expm to work, are:-
dgpadm - Padé approximation of dense, double precision matrix.
zgpadm - Padé approximation of dense, complex matrix
dgexpv - Krylov projection of general sparse, double precision matrix
zgexpv - Krylov projection of general sparse, complex matrix
However, there are routines optimised for other specific types of matrices, including symmetric and Hermitian dense and sparse matrices. It might be desirable to keep the wrappers for these routines, even though I don't think they are currently available in SciPy's expm[23] functions...
I hope this helps to get things moving along.
Kind regards,
Alex