Repository navigation
ENH: implement np.unwrap as a generalized ufunc - #31848
Conversation
Signed-off-by: Iason Krommydas <[email protected]>
Signed-off-by: Iason Krommydas <[email protected]>
Signed-off-by: Iason Krommydas <[email protected]>
Signed-off-by: Iason Krommydas <[email protected]>
Signed-off-by: Iason Krommydas <[email protected]>
np.unwrap as a gufuncnp.unwrap as a generalized ufunc
Signed-off-by: Iason Krommydas <[email protected]>
Signed-off-by: Iason Krommydas <[email protected]>
|
FYI this is what one gets with the current unwrap testing on main. Some error messages are different here versus main and naturally on main subclasses are not returned. But I'd argue for the cases that unwrap shouldn't work anyways, the error messages are a bit better now instead of overflow errors and |
Signed-off-by: Iason Krommydas <[email protected]>
Signed-off-by: Iason Krommydas <[email protected]>
Signed-off-by: Iason Krommydas <[email protected]>
Signed-off-by: Iason Krommydas <[email protected]>
|
IMO this should be ready for a review pass |
Signed-off-by: Iason Krommydas <[email protected]>
MaanasArora
left a comment
There was a problem hiding this comment.
I didn't look very deeply, but will do so very soon - this looks nice, thanks! Just one bug, and mostly doc comments otherwise for now.
Signed-off-by: Iason Krommydas <[email protected]>
Signed-off-by: Iason Krommydas <[email protected]>
ngoldbaum
left a comment
There was a problem hiding this comment.
OK, first off, I'm very happy with the performance improvements. As I'm sure you know, I'm very happy with doing this sort of thing to improve performance of NumPy in ways that are natural in the codebase.
Now given that, I think we should probably check in with the numpy-discussion mailing list before actually merging the PR. While this is mostly not user-visible (except via the performance and memory improvements) this does add a new ufunc to numpy, which downstream libraries are going to have to deal with. @mhvk can check in with an astropy hat on probably but there are lots of other smaller projects that this will impact as well. IMO it's worth it but it's worth pinging the mailing list to check in first.
I also did a review pass and noticed some issues that'll need to be addressed. I may spot more stuff on a further pass but hopefully we'll converge quickly after this first pass is addressed.
|
Thanks for the review! @ngoldbaum I'll address everything in the coming week as best as I can. |
Signed-off-by: Iason Krommydas <[email protected]>
Signed-off-by: Iason Krommydas <[email protected]>
|
Or I have one more idea. We get rid of the whole python promotion and passing |
|
I agree with Marten it doesn't seem to make much sense to keep e.g. |
ngoldbaum
left a comment
There was a problem hiding this comment.
I spotted a couple minor issues with a claude review pass. I think C promoters are generally what you want instead of implementing promotion logic in the Python wrapper, but I'll defer to Maanas and Sebastian's opinions.
There was a problem hiding this comment.
Just two fly-by nits... the discont handling still needs to be resolved of course.
For the promotion logic, I'm not sure if C is the right level. We only need to do what PyArray_ResultType does, but this is mostly just legacy behavior, not sure if it will be simpler enough as we handle non-builtins too. But maybe Sebastian has a better idea if it's worth it.
|
Because I know very little about implementing promoters, I had claude generate me one to see the idea and pushed it in another branch. This is the commit: ikrommyd@c32bc51. Do you think we should go into that direction? |
Signed-off-by: Iason Krommydas <[email protected]>
|
I still don't think we should care about specializing precision for |
|
Main's output dtype is |
|
I agree casting to But even right now, an explicit |
|
I'd be fine with casting to |
ngoldbaum
left a comment
There was a problem hiding this comment.
I think @MaanasArora and @ikrommyd have actually converged on a design, see my comment below. I think a one-liner is better than a C++ promoter.
|
Is it a thing to do multiple release notes like an improvement + another one for behavior changes or should everything go into the same |
|
Two different release notes are a thing, you can add a second one for the changes. |
Signed-off-by: Iason Krommydas <[email protected]>
Signed-off-by: Iason Krommydas <[email protected]>
Signed-off-by: Iason Krommydas <[email protected]>
|
@ngoldbaum @MaanasArora I believe I have addressed the comments and have added the converged dtype logic in 86a2566 |
ngoldbaum
left a comment
There was a problem hiding this comment.
LGTM! I'd appreciate it if one of Maanas or Marten could look this over and hit the merge button if they approve.
Also maybe worth a ping to the mailing list as a head's up for downstream maintainers who try to be fully compatible with all NumPy ufuncs. That's pretty much just astropy (and Marten already knows) but it may be other people too.
MaanasArora
left a comment
There was a problem hiding this comment.
Looks good to me! Thanks for the changes, I think the dtype resolution comes together quite nicely. I didn't look very closely at the tests but they seem thorough. In it goes... thanks @ikrommyd for the nice improvement!
|
Thank y'all for the reviews! Cheers! |
PR summary
Closes #9959
This PR implements
np.unwrapas a generalized ufunc. We have to preserve the python wrapper to keep the API intact.While making this PR I also found that unwrap had a docstring and typing issue. It's period argument can be an integer too and when both the input array and period are integers, the output dtype is also an integer. This was already shown in the docstring examples but not reflected in the types and typing stubs. I fixed both here.
The core of unwrap is now a generalized ufunc in C++ (signature
(n),(),()->(n)). The loop is implemented with discont argument always being a double as the function asks for it to be a python float.As a result, unwrap now preserves the ndarray subclasses rather than always returning a base ndarray which is what the issue wanted at the time.
I chose not to add an object dtype C++ loop here as that is way too complicated for what it offers because I assume there is very little use of unwrap for object dtypes. We fall back to the old python implementation for object dtypes. I vibe coded an object dtype loop and it's 2x faster than the fallback on my machine but I think it's not worth having this complicated C++ code for this.
For integer/float dtypes, I see a nice 2x - 3x speed improvement on my machine from limited benchmarking and memory should be improved too as the fused loop avoids copies.
As unwrap had very limited testing, I added tests here that all pass on
mainexcept thetest_subclass_preservedof course because until now unwrap did not preserve ndarray subclasses.AI Disclosure
AI tools were used to help me translate the python implementation algorithm into the C++ loop. The documenting comments above the loop were also written by AI after I asked it (but I don't know if those are useful and can be removed).