Open Bernmeister opened 3 years ago
Thanks very much for the very complete example script! It worked the first time I tried it, and let me dive in immediately.
compute()
. Originally it did, but it turns out most users only ask for one or two facts about an object, not for everything, so to speed things up it just caches the (a) observer and (b) date, then access to actual attributes trigger computation. So try adding a line comet.a_ra, comet.a_dec, comet.hlon, comet.hlat
right after the compute()
call. It’s still pretty quick, but not as quick as when PyEphem does no work.I tried profiling the code with cProfile
with:
python -m cProfile -o _profile.out tmp.py
And then dumped the resulting profile to the screen:
python -c '__import__("pstats").Stats("_profile.out").strip_dirs().sort_stats("tottime").print_stats()'
It looks like much of the time is spent in the functions stumpff()
and propagate()
:
Wed Nov 25 17:03:03 2020 _profile.out
1196835 function calls (1186925 primitive calls) in 4.390 seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
8095 1.179 0.000 2.372 0.000 keplerlib.py:401(stumpff)
148 0.495 0.003 3.445 0.023 keplerlib.py:445(propagate)
74441 0.438 0.000 0.438 0.000 {method 'reduce' of 'numpy.ufunc'
objects}
7947 0.211 0.000 2.540 0.000 keplerlib.py:507(kepler)
24285 0.203 0.000 0.399 0.000 shape_base.py:1069(tile)
...
@JoshPaterson — If I recall, you are the expert on those routines. Do you have any ideas about how they spend most of their time? Or about what directions we might explore to see if they could be increased in speed?
For comparison, I think PyEphem does some trigonometry instead of trying to propagate directly with vectors:
https://github.com/brandon-rhodes/pyephem/blob/master/libastro-3.7.7/twobody.c
Hah! I'm glad I looked at this issue. I had an application a couple of weeks ago that needed the previous antitransit for the Sun. We have an ephemeris class that wraps PyEphem. This class has a public method get_object('Sun')
that calls a private method that returns ephem.Sun()
. After doing this it calls compute()
. I looked at the code for PyEphem and saw that previous_antitransit()
calls compute()
again. I searched high and low to see what exactly compute()
did to no avail, so I decided to access the private method to get ephem.Sun()
in order to avoid calling compute()
twice. Now I know that was unnecessary.
I'm a little surprised at how much time is spent in stumpff
. It gets called so often because there's a root finding algorithm in propagate
and stumpff
is used in computing the objective function.
I think the best chance of getting orders of magnitude improvement in speed would be to vectorize propagate
so that it can take a vector of objects and a vector of times and return a two dimensional array of positions.
I'll take a look at what can be optimized in stumpff
and propagate
(I already see some things), and I will also try to vectorize propagate
.
@JoshPaterson @brandon-rhodes Wondering (as politely as possible) how this is progressing? I'm somewhat stuck in PyEphem (which has served me well for many years), but am keen to finally move over to Skyfield.
As I understand, the solution is to take a vector of object and process in that manner? If so, would that then apply to stars and planets?
I noticed over the last couple of weeks the Minor Planet Center seems to have dropped support for data files for minor planets for formats other than their native MPC format. That means users of PyEphem can no longer use MPC data (except for comets). I guess this makes Skyfield the front-runner as it were as Skyfield uses the MPC format. Any update please on how this work is proceeding to (hopefully) speed up processing of large numbers of comets / minor planets?
I did toy with the idea of taking data files in MPC format for minor planets and convert to PyEphem/XEphem format...but I don't believe all the data is present in the MPC format which is required in the XEphem format to do a successful conversion. Would have been a neat workaround...oh well.
Any progress on this front? I'm trying to calculate some daily positions with comets and minor planets over long periods of time, and as it stands it's still astronomically (good pun indeed) slow.
When computing comets (and minor planets) with Skyfield, the time to do so is astronomically (pardon the pun) greater than that for PyEphem. I understand PyEphem uses a C backend and so will always be faster, but this appears to be orders of magnitude faster. Hoping this is a quick fix and I've made yet another school boy error!
The test script below computes comets and minor planets for each of Skyfield and PyEphem:
The results:
Some points to note:
The bizarre way in which I load the data for Skyfield from file only to write back out to a memory file (or whatever it is called) mimics my final application as I need to currently support PyEphem and Skyfield and at the same time, cache the data files so as to not annoy the Minor Planet Center. Regardless, I've timed the file processing code versus the computation part and it is the computation part which is expensive.
Using
importlib.import_module
to dynamically invoke the correct function call again (seemingly) incurs little to no overhead to the overall timing.Computing the observer on each iteration for PyEphem makes little impact to timing (but PyEphem is not the slow horse in this race).
I chose the smallest sample of data file Bright for the Minor Planet test. Ultimately I want to use data files for each of Critical, Distant and Unusual.