-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
SkyCoords very slow due to FRAME_ATTR_NAMES_SET #5698
Description
Can we replace FRAME_ATTR_NAMES_SET() with a lazily-reevaluated version? This would cure a lot of speed woes with SkyCoord.
Just creating a SkyCoords object, or accessing an attribute, is very slow (milliseconds or millions of clock cycles) regardless of whether it is one point or a thousand. Profiling shows that the time is almost all spent in FRAME_ATTR_NAMES_SET() sky_coordinate.py:38 :
%timeit x=SkyCoord(5,5,unit=u.deg)
100 loops, best of 3: 3.03 ms per loop
%timeit x=SkyCoord(np.linspace(0,360,1000),np.arange(0,360,1000),unit=u.deg)
100 loops, best of 3: 3.07 ms per loop
x=SkyCoord(5,5,unit=u.deg, frame='fk5')
%timeit x.equinox
1000 loops, best of 3: 846 µs per loop
%prun x=[SkyCoord(5,5,unit=u.deg) for i in range(1000)]
from astropy.coordinates.sky_coordinate import FRAME_ATTR_NAMES_SET
%timeit FRAME_ATTR_NAMES_SET()
1000 loops, best of 3: 875 µs per loop
The profiling shows that FRAME_ATTR_NAMES_SET calls getattr() 252 times each time it is called, which is believable given that the code walks a tree:
def FRAME_ATTR_NAMES_SET():
"""Set of all possible frame-specific attributes"""
out = set()
for frame_cls in frame_transform_graph.frame_set:
for attr in frame_cls.get_frame_attr_names().keys():
out.add(attr)
return out
To make astropy less slow, can we do some caching so that it doesn't have to be re-evaluated every single time somebody looks at a SkyCoord attribute or makes a new SkyCoord?
(Do we have to worry about invalidating the cached value? Can we invalidate the cached value if frame_transform_graph.frame_set is changed?).