-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
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
Conversation
c6c8293
to
b022ab1
Compare
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): |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
).
cbook._step_validation(np.arange(12), 'a') | ||
|
||
with pytest.raises(ValueError): | ||
cbook._step_validation(np.arange(12)) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
I am mostly 👍 on this, tad concerned about the immutable -> mutable change in the return type. |
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 All of the widows test are failing on conda-build related issues. |
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] |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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:] |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This belongs up here.
There was a problem hiding this comment.
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.)
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
put it back there.
b022ab1
to
ee3ff2f
Compare
Can we remove them without a deprecation period? :-) |
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 😉 |
Too late, they're dead now :-) |
7a0fcc1
to
7f199c7
Compare
@@ -0,0 +1,6 @@ | |||
Functions removed from the `lines` module |
There was a problem hiding this comment.
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'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved.
One major issue with this is that it is going to strip units and cast everything to a float. attn @dopplershift |
That (casting everything to a float) was already the case before? |
7f199c7
to
80779ea
Compare
This is true. Should not hold the PR over that, but we will probably have to address the units sooner or later. |
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:] |
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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).
80779ea
to
cd2608e
Compare
The previous implementation of
pts_to_{pre,mid,post}
step was fairlyunefficient: 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).