Repository navigation
Speed up distance calculations by ~10-20x - #3767
Conversation
* Break out some internal functions for the integrators to call directly * Tests pass, distances are about 10x faster than before, now about 5x faster than cosmolopy. This is only done for a) distances, b) FlatLambdaCDM. The idea is to show exactly how ugly this solution is so we can decide if it's worth implementing for the other cosmologies. Sure does speed things up though...
* Unwrap the distance function to integrate for other classes * Note that cosmologies with massive neutrinos are still very slow, as nu_relative_density is apparently quite expensive to calculate. Added a note to this effect to the docs. * Remove an unused assignment to Ok0
|
Would changing all |
|
Short answer: No. That's what Note that getting rid of the isiterables is only about a factor of 2-3x speedup. Having individual functions that avoid calculating things they don't need to is another 2-3x speedup. |
|
To provide a slightly more nuanced option: a big chunk of the expense is that
So we could only have two "special" versions of the scalar integrand: with massive neutrinos, and without, and could eliminate the no-radiation version. That's only like 5-10% slower than the fast version. My thinking was once I'm committed to having two ugly internal versions of |
|
About I see your point about the individual functions to avoid unnecessary calculations, though. I guess we can't avoid making special versions of integrands for that. |
|
Wouldn't the computation that fails on an array just be the "special" functions that use |
There was a problem hiding this comment.
Why make this change? The function gets only passed on once.
There was a problem hiding this comment.
That's a leftover from an earlier attempt to make it faster.
|
@aconley - Speed-ups for common cases are a good idea, and I think that by factoring out some of the boilerplate code, this could be made to look a lot less ugly (see inline comments). |
|
In case you want to profile the code, you can see if https://jiffyclub.github.io/snakeviz/ works for you. |
|
If it is 10x improvement, I think speed outweighs ugliness. Pretty codes that no one uses are useless. |
|
I should point out: the Planck cosmologies, which I imagine will become the default fairly soon, are still very slow. That's because they include massive neutrinos, and that turns out to be quite expensive. So the next effort -- even if this one is rejected -- should be to try to figure out how to make that faster. |
* Add internal variables _scalar_inv_efunc and _scalar_inv_efunc_args set by the constructor that are used for integrands. This allows us to remove overloading of comoving_distance. * Minor tweaks to specialized integral forms to make them faster. * Add some unit tests of a wider range of cosmologies to ensure all the fancy new bits work. * Add vectorize_if_needed helper function.
There was a problem hiding this comment.
It will be much faster for scalars if we assume a scalar and catch the exception instead of using isiterable:
def vectorize_if_needed(func, x):
""" Helper function to vectorize functions on array inputs"""
try:
return func(x)
except TypeError:
return np.vectorize(func)(x)
This will be a little slower for array inputs. But I think that's ok, because in that case there typically won't be a large number of function calls.
There was a problem hiding this comment.
Unfortunately that doesn't work, because you can't guarantee that func will fail with a TypeError. For example, if I try your suggested change change, scipy.integrate.quad fails with ValueErrors. A lot. And I'm leery of just catching any exception.
There was a problem hiding this comment.
Ok. I also tested this and the speedup is not so important, so it's fine as you have it.
|
I completely agree a 10x speedup is worth any ugliness. Note the current version breaks backwards compatibility for |
|
Hmm... I don't like people using Would it be acceptable to create promoted non-scalar versions |
…gelog. Changes to external visibility of absorption and time integrands. The idea is to eventually turn _xfunc, _tfunc into pure scalar versions used in the integrations, but provide a vectorized version publicly for anyone who needs it. * Add externally visible xfunc, tfunc to FLRW that can still handle vectors for people that use them. * Keep _xfunc _tfunc as able to handle vectors in case anybody out there was being bad and using things beginning with _. Add deprecation warning telling people to use xfunc, tfunc instead. * Add _xfunc_scalar, _tfunc_scalar for integrals. Some internal plumbing changes: * rename scalar inv efunc functions to include class name. This is to avoid pylint from complaining about overloaded functions with different numbers of variables. * Make Flat cosmologies call their superclass constructors instead of FLRW.__init__. * Remove some dead code in angular_diameter_distance_z1z2 -- it was swapping z1, z2 if they were out of order, but that couldn't be reached because the previous line was raising an error for that condition anyways (since swapping doesn't work for array z1, z2 anyways!). Add some tests * Add some tests of the different distance integrands to make sure nothing got broken. These just compare to what HEAD got before the speedup rather than external sources -- but caught some bugs, and so are totally worth including! * Some additional minor unit tests, mostly to get the coverage checker to shut up about reduced coverage. If the idea of adding that was to shame people into adding more tests, well, apparently it works on me.
|
@nhmc -- the recent update returns You don't want to use |
There was a problem hiding this comment.
Could you change this to _inv_efunc_scalar for consistency with _tfunc_scalar and _xfunc_scalar?
|
They definitely have no right to be annoyed, but that doesn't stop them from getting annoyed and tweeting 'astropy broke my code!' I left some inline comments, but everything else looks fine to me. |
…xt]func * Change depracation warnings on `_tfunc`, `_xfunc` to no longer say they will become scalar. * Added non-standard subclass test for efunc, inv_efunc
|
Hmm... something went screwy with Travis. It doesn't seem to have |
|
@aconley - remember that only some of the travis builds have optional dependencies (including scipy) installed - you need to make sure the tests are skipped if scipy is not installed. |
* It turns out that one of the new tests requires scipy because it -- unlike the built-in-subclasses- actually calls de_density_scale.
|
@astrofrog -- yeah, I knew that. I just didn't think I had added any tests that required scipy, and it turns out I had in a slightly subtle fashion. Anyways, finally should be ready to go. |
|
I also agree this is enough of a speedup to justify the ugliness, especially given the importance of this to plenty of modern astro. I'm happy with most of it, but two relatively straightforward items:
And just to make sure we're all on the same page, you'd rather address any possible optimizations for the massive neutrinos in a later separate PR, right @aconley? |
|
@eteq -- definitely. I looked at the neutrinos briefly, and it seems like it will be harder, so it makes sense to do this in stages. I don't think we should rename |
* xfunc -> abs_distance_integrand * tfunc -> loockback_time_integrand * Fix call in age to use _scalar version * Add a long note to the top of cosmology/core.py describing how to use the scalar distance integrand speedups for interested parties. * Briefly point users to that note from sphinx cosmology docs.
|
Awesome. This looks great and everything is passing, so I'll go ahead and merge. Thanks @aconley ! |
Speed up some cosmology distance calculations by ~10-20x
* Follow on to astropy#3767, which is partially addressing astropy#3764 * Add scalar function to compute massive neutrino densities in integrals to get speedup for arbitrary number of neutrinos. This buys about 20% speedup. * Add 1, 2, and 3 massive neutrino specializations for much larger speedups by avoiding the (surprisingly) expensive numpy.sum operations. These should be by far the most common cases. * Some unit tests added for the new scalar functions
Speed up some cosmology distance calculations by ~10-20x
Speed up some cosmology distance calculations by ~10-20x
directly
about 5x faster than cosmolopy.
This is only done for a) distances, b) FlatLambdaCDM. The idea
is to show exactly how ugly this solution is so we can decide
if it's worth implementing for the other cosmologies. Sure
does speed things up though...