Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Avoid temporaries when preparing step plots. #7454

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

Merged
merged 1 commit into from
Nov 15, 2016

Conversation

anntzer
Copy link
Contributor

@anntzer anntzer commented Nov 14, 2016

The previous implementation of pts_to_{pre,mid,post}step was fairly
unefficient: it allocated a large array during validation (vstack),
then a second array to build the return tuple, then converted the
columns to a tuple, then immediately converted the tuple back to a new
array at the call site (to construct a Path). Instead, just create a
single array and work with it all along.

Also some minor related cleanups (moving imports in lines.py, in
particular suggesting to not expose the individual pts_to_*step
functions anymore (they are not directly used, only via the
STEP_LOOKUP_MAP mapping).

steps = np.zeros((1 + len(args), 2 * len(x) - 1))
steps[0, 0::2] = x
steps[0, 1::2] = steps[0, 0::2][:-1]
for out, y in zip(steps[1:], args):
Copy link
Member

Choose a reason for hiding this comment

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

This is trading memory duplication for a python for-loop. Did you bench mark this it terms of time?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually the previous implementation also had a for loop over the arguments during validation (line 2314 args = tuple(np.asanyarray(y) for y in args)). So we're even on that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But in fact I can even do without that loop -- see latest version.

x = np.asanyarray(x)
if x.ndim != 1:
raise ValueError("x must be 1 dimensional")
if len(args) == 0:
Copy link
Member

Choose a reason for hiding this comment

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

Looks like this no longer raises if there are no y-values. I think I am 👍 on this, but just checking that it was intentional.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I even removed the test for that (test_step_fails).

@tacaswell tacaswell added this to the 2.1 (next point release) milestone Nov 14, 2016
cbook._step_validation(np.arange(12), 'a')

with pytest.raises(ValueError):
cbook._step_validation(np.arange(12))
Copy link
Member

Choose a reason for hiding this comment

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

This test case got dropped.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

See comment above re don't error when no y is passed.

@tacaswell
Copy link
Member

I am mostly 👍 on this, tad concerned about the immutable -> mutable change in the return type.

@tacaswell
Copy link
Member

Looks like the tuple return is legacy of how the step logic got factored out the line code. I wrote it and no longer remember why.

+0.5 on removing the pts_to_* function from the lines.py namespace (with an API changes note), but leaving them does little harm.

All of the widows test are failing on conda-build related issues.

@tacaswell tacaswell changed the title Avoid temporaries when preparing step plots. [MRG+1] Avoid temporaries when preparing step plots. Nov 14, 2016
return tuple(steps)
steps = np.zeros((1 + len(args), 2 * len(x) - 1))
steps[0, 0::2] = x
steps[0, 1::2] = steps[0, 0::2][:-1]
Copy link
Member

Choose a reason for hiding this comment

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

Is there any reason to use two slices here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I find this easier to read -- otherwise can you tell immediately whether it should be steps[0, 0:-1:2] or steps[0, 0:-2:2]? Also, I'm not writing x[-1] because that slicing may be not so cheap (I'm looking at you xarray). Same reasons apply below.

Copy link
Member

Choose a reason for hiding this comment

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

Either one works, so I guess that's just up to you...

I'm not sure to which x[-1] you are referring in the second sentence?

return tuple(steps)
steps = np.zeros((1 + len(args), 2 * len(x) - 1))
steps[0, 0::2] = x
steps[0, 1::2] = steps[0, 0::2][1:]
Copy link
Member

Choose a reason for hiding this comment

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

Again, any reason for two slices?

@@ -7,32 +7,29 @@
from __future__ import (absolute_import, division, print_function,
unicode_literals)

import six
Copy link
Member

Choose a reason for hiding this comment

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

This belongs up here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The PEP8 order is stdlib (warnings), third-party (numpy, six) and internals (everything else). Do we prefer always putting six first? (I don't really care.)

Copy link
Member

Choose a reason for hiding this comment

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

Yes, I know; six is analogous to a future-import in our ordering.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

put it back there.

@anntzer
Copy link
Contributor Author

anntzer commented Nov 14, 2016

Can we remove them without a deprecation period? :-)
(There's actually quite a few such imports that could be removed; something such as https://pypi.python.org/pypi/metamodule/ could be useful.)

@tacaswell
Copy link
Member

They have only been there from 1.5.0 on so relatively young. If @anntzer is concerned, I am perfectly happy to leave the imports in place 😉

@anntzer
Copy link
Contributor Author

anntzer commented Nov 14, 2016

Too late, they're dead now :-)

@anntzer anntzer force-pushed the step-converters branch 2 times, most recently from 7a0fcc1 to 7f199c7 Compare November 14, 2016 15:37
@@ -0,0 +1,6 @@
Functions removed from the `lines` module
Copy link
Member

Choose a reason for hiding this comment

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

This seems more 'api_changes' than 'whats_new'

Copy link
Contributor Author

Choose a reason for hiding this comment

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

moved.

@tacaswell
Copy link
Member

One major issue with this is that it is going to strip units and cast everything to a float.

attn @dopplershift

@anntzer
Copy link
Contributor Author

anntzer commented Nov 14, 2016

That (casting everything to a float) was already the case before?

@tacaswell
Copy link
Member

This is true. Should not hold the PR over that, but we will probably have to address the units sooner or later.

@dopplershift
Copy link
Contributor

So long as it's no worse than before, it's fine by me. I'll just keep this in the back of my mind until I need a step plot.

steps[0, 0::2] = x
steps[0, 1::2] = steps[0, 0::2][:-1]
steps[1:, 0::2] = args
steps[1:, 1::2] = steps[1:, ::2][:, 1:]
Copy link
Member

@QuLogic QuLogic Nov 14, 2016

Choose a reason for hiding this comment

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

This is one place where I find two slices more confusing.
Start at 2 and take every other one, is much clearer than take every other one and start at 1 (which is really 2 from the original array).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, I squashed the two slices together.

The previous implementation of `pts_to_{pre,mid,post}`step was fairly
unefficient: it allocated a large array during validation (`vstack`),
then a second array to build the return tuple, then converted the
columns to a tuple, then immediately converted the tuple back to a new
array at the call site (to construct a Path).  Instead, just create a
single array and work with it all along.

Also some minor related cleanups (moving imports in lines.py, in
particular not exposing the individual `pts_to_*step` functions anymore
(they are not directly used, only via the `STEP_LOOKUP_MAP` mapping).
@tacaswell tacaswell merged commit 901562f into matplotlib:master Nov 15, 2016
@QuLogic QuLogic changed the title [MRG+1] Avoid temporaries when preparing step plots. Avoid temporaries when preparing step plots. Nov 15, 2016
@anntzer anntzer deleted the step-converters branch November 15, 2016 03:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants