Skip to content

A few speedups related to SkyCoord.__getitem__ - #3337

Closed
embray wants to merge 8 commits into
astropy:masterfrom
embray:coordinates/minor-speedups
Closed

embray wants to merge 8 commits into
astropy:masterfrom
embray:coordinates/minor-speedups

Conversation

@embray

@embray embray commented Jan 22, 2015

Copy link
Copy Markdown
Member

Here's a small collection of speedups aimed at the test case from #3323. These are very specifically aimed at that one case, but may help in other cases as well:

In [1]: import numpy as np
In [2]: from astropy import units as u
In [3]: from astropy.coordinates import SkyCoord
In [4]: ra = np.random.uniform(0, 360, size=1000) * u.deg
In [5]: dec = np.random.uniform(-90, 90, size=1000) * u.deg
In [6]: crd = SkyCoord(ra, dec)
In [7]: %timeit [c for c in crd]
1 loops, best of 3: 19.3 s per loop

with the speedups in this branch I now get:

In [3]: %timeit [c for c in crd]
1 loops, best of 3: 2.47 s per loop

so improvement by an order of magnitude. There are plenty other things that could be done, but I shouldn't spend any more time on it right now (I may come back to it later). There are also a few open questions I left in the code as # TODO comments that might be worth a look.

One of them in particular is that this obviates the need for the FRAME_ATTR_NAMES_SET function, which I think could either be removed outright (since it isn't documented), or at least deprecated.

…ke frame_set. Use this to implement the FRAME_ATTR_NAMES_SET() 'macro' which speeds it up significantly (it could be removed entirely at this point, or at least deprecated, though it's used so frequently in the sky_coordinate module that it might still be useful to have a module-level alias to it)
… each attribute as a lambda. Might be nice to speed this up on the class-level as well which might be doable in some cases since frame attributes, for example, are per-class. Still trickier though.
…be calculated repeatedly in the loop. However, also removed a variable (n_attr_names) that was something of an unnecessary and premature 'optimization'
…ngle, and a few workarounds to performance shortcomunings in units.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The performance gains from this change are marginal in most cases, but in a loop it does make a difference when the same attributes are looked up over and over again.

@embray

embray commented Jan 26, 2015

Copy link
Copy Markdown
Member Author

That's weird that those table tests failed. Not sure what that's about (none of the actual direct tests of the coordinates package failed). I'll have a look at it later.

@mhvk

mhvk commented Jan 26, 2015

Copy link
Copy Markdown
Contributor

@embray - I don't quite understand why the speed-ups to Angle and Longitude should be necessary in your example. Your example should only take elements from the Longitude array, so why is the wrapping relevant at all? Why does the wrap angle even get set? It seems somewhere the code reinitializes Longitude and Latitude when there is no need to. Do you know where this is? (Sorry, while I know Angle and its subclasses well, I'm not very familiar with Coordinates.)

@embray

embray commented Jan 26, 2015

Copy link
Copy Markdown
Member Author

@mhvk Currently (and this in of itself is probably not ideal--I was just adding what speedups I could without otherwise changing the current logic), every time SkyCoord(self) is called, the initializer calls _parse_coordinate_arg which in turn calls coords.data.represent_as(frame.representation), which in turn ends up instantiating a new SphericalRepresentation every time, which initializes a new Latitude and Longitude here (though by default I think it's passing in existing Latitude and Longitude objects, which could probably be initialized faster when copy=True) but I'm not sure.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Of all the changes in this code this is one of the most relevant. But though instantiating the default wrap angle over and over again also hurt quite a bit in a loop.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Fine to keep this of course! (Am slightly dismayed that it matters so much...)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Not a huge amount but it was still an improvement.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Interestingly, instantiating an Angle from an existing Angle is no faster than instantiating one from a Quantity (such as 360 * u.deg). In fact it may even be a smidge slower. That's not including the instantiation of the Quantity itself. We're talking Angle(a) vs. Angle(q). (not to say it's terribly slow in the first place)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm looking at Angle initialisation right now. Hope to have a PR to your branch shortly...

@mhvk

mhvk commented Jan 27, 2015

Copy link
Copy Markdown
Contributor

@embray - after comments in #3323, I realised that the angle stuff will all be unnecessary if in BaseRepresentation.__getitem__ one would not use the class initialiser but instead have a class method that simply sets the required attributes..

@embray

embray commented Jan 27, 2015

Copy link
Copy Markdown
Member Author

At least some of the speedups in Angle still seem worthwhile regardless.

@mhvk

mhvk commented Jan 27, 2015

Copy link
Copy Markdown
Contributor

@embray - agreed that some are good to do anyway. I mostly don't like the ones that have TODO comments.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These changes are all fine.

@mhvk

mhvk commented Jan 27, 2015

Copy link
Copy Markdown
Contributor

p.s. My guess would be that much of the gain of the TODO items could be made by optimizing Angle.__new__ (just like Quantity.__new__ could be sped up, but I never got around to doing Angle as well).

@embray

embray commented Jan 27, 2015

Copy link
Copy Markdown
Member Author

I agree on that last comment--I thought of looking into it but Angle.__new__ went into Quantity.__new__ and it was just a rabbit hole so I stopped looking, at least at the time.

@mhvk

mhvk commented Jan 27, 2015

Copy link
Copy Markdown
Contributor

We tried very hard to make sure Quantity.__new__ is as fast as possible if the input value is a Quantity, type(value) is cls, no unit or dtype change is necessary, and copy=False. I think for any Angle(angle), Quantity.__new__ should be about as fast as one can hope for, with the main speed-up possible by adding copy=False (if this is reasonable, e.g., if one knows a copy has already been made or is otherwise not needed).

@embray

embray commented Jan 30, 2015

Copy link
Copy Markdown
Member Author

I'm still having a hard time understanding the test failures here, particularly in the table_mixin tests. It seems that test_join passes for regular tables, but then fails when using MaskedTable or any other Table subclass. It's strange, really...

@mhvk

mhvk commented Jan 30, 2015

Copy link
Copy Markdown
Contributor

Yes, that fails also with the changes I made... Unfortunately, the table tests are so convoluted with things being set up in conftest.py that it is very hard to reproduce on a simpler example. It does seem that there somehow are too many sky coordinates.

@embray

embray commented Jan 30, 2015

Copy link
Copy Markdown
Member Author

Well, it turns out all the table failures are related to my "enhancements" to SkyCoord.__getattr__. What happens seems to have something to do with the self._sky_coord_frame switcheroo that happens in SkyCoord.__getitem__. In the case of some of the table tests, the original self._sky_coord_frame is being sliced, so this replaces it with a new frame. However, any cached attribute lookups on self are now referencing the wrong frame, which leads to problems.

The attribute lookup speedups are not insignificant, but they're not the most significant improvement in this PR either. So if it ends up overcomplicating things I'll just remove it. Though the way SkyCoord.__getitem__ works currently still seems ripe for improvement...

@eteq

eteq commented Feb 4, 2015

Copy link
Copy Markdown
Member

@embray - other than the attribute lookup stuff this should be good, right? So maybe you should just remove that part so we can get partial speedups in for 1.0, and then try to get the attribute speedups as a later PR for 1.0.x?

Or might this be a bit too late for 1.0 anyway, given that it's doing quite a bit deep in the plumbing of SkyCoord...?

@astrofrog

Copy link
Copy Markdown
Member

Given that this is still failing on the CI I'd actually just vote to include it in 1.0.1 (I think we ruled in the past that performance fixes were ok in minor releases because they don't change the API).

@eteq

eteq commented Feb 4, 2015

Copy link
Copy Markdown
Member

ok, sounds good - will assign it that milestone then.

@eteq eteq added this to the v1.0.1 milestone Feb 4, 2015
@landscape-bot

Copy link
Copy Markdown

Code Health
Repository health increased by 10% when pulling 4399914 on embray:coordinates/minor-speedups into 0233c22 on astropy:master.

@embray

embray commented Feb 6, 2015

Copy link
Copy Markdown
Member Author

Yeah, I think it's best to delay this for now. I have thoughts on how to fix the attribute lookup thing so that it can still be benefitted from.

Meanwhile, what the heck is landscape-bot?

@embray embray modified the milestones: v1.0.2, v1.0.1 Mar 4, 2015
Comment thread astropy/units/core.py

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@embray - I don't particularly like this change -- it adds complexity when at least for larger arrays the main culprit in making things slow is that the conversion has to involve making a copy (the scale determination is very fast, especially if units are the same). Also, my feeling is that this is the wrong place to optimize this -- the converter shouldn't even be called when the units are the same.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I agree, I just haven't had a chance to work on this more.

@embray

embray commented Apr 8, 2015

Copy link
Copy Markdown
Member Author

Dropping this from the milestone until I have a chance to address the issues here.

@bsipocz

bsipocz commented May 9, 2017

Copy link
Copy Markdown
Member

@eteq @adrn @mhvk - This branch still seems to be faster than current master. Is there any chance to cherry-pick stuff from here to get things moving and close this PR?

@mhvk

mhvk commented May 9, 2017

Copy link
Copy Markdown
Contributor

Definitely a good idea, though I sadly don't see myself having time to work on this soon.

@pllim

pllim commented May 11, 2017

Copy link
Copy Markdown
Member

Conflicts and seems to have been replaced by #5598

@pllim pllim closed this May 11, 2017
@bsipocz

bsipocz commented May 11, 2017

Copy link
Copy Markdown
Member

@pllim - is that PR have everything from here?

@pllim

pllim commented May 11, 2017

Copy link
Copy Markdown
Member

Actually no, but this has a better chance of being completed if @mhvk "absorbs" it rather than sitting around here.

@mhvk

mhvk commented May 11, 2017

Copy link
Copy Markdown
Contributor

If this is closed, I'll simply never see it anymore, so I'll leave it open for now. I'll also set the milestone to 3.0; if this is seen then and nothing happened, just close.

@mhvk mhvk reopened this May 11, 2017
@mhvk mhvk added this to the v3.0.0 milestone May 11, 2017
@astropy-bot

astropy-bot Bot commented Sep 27, 2017

Copy link
Copy Markdown

Hi humans 👋 - this pull request hasn't had any new commits for approximately 2 years. I plan to close this in a month if the pull request doesn't have any new commits by then.

In lieu of a stalled pull request, please close this and open an issue instead to revisit in the future. Maintainers may also choose to add keep-open label to keep this PR open but it is discouraged unless absolutely necessary.

If you believe I commented on this issue incorrectly, please report this here.

@mhvk

mhvk commented Sep 27, 2017

Copy link
Copy Markdown
Contributor

At this stage it is probably best to raise issues for the various fixes that were proposed here, and that were not yet implemented.

@astropy-bot

astropy-bot Bot commented Nov 21, 2017

Copy link
Copy Markdown

⏰ Time's up! ⏰

I'm going to close this pull request as per my previous message. If you think what is being added/fixed here is still important, please remember to open an issue to keep track of it. Thanks!

If this is the first time I am commenting on this issue, or if you believe I closed this issue incorrectly, please report this here.

@astropy-bot astropy-bot Bot closed this Nov 21, 2017
@astrofrog astrofrog added the closed-by-bot Closed by stale bot label Nov 21, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants