-
-
Notifications
You must be signed in to change notification settings - Fork 11k
ENH/DEP: Use a ufunc under the hood for ndarray.clip #12519
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
if you have a ready benchmark, perhaps you could add it? |
numpy/core/src/umath/loops.c.src
Outdated
npy_intp n = dimensions[0]; | ||
npy_intp i; | ||
|
||
/* contiguous, branch to let the compiler optimize */ |
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.
Just enough optimization here to make um.clip
faster than np.clip
in the cases that are common.
a00d605
to
c74d00e
Compare
Outdated but non-resolved comments above still apply |
c74d00e
to
348e3f6
Compare
348e3f6
to
4989ee1
Compare
numpy/core/_methods.py
Outdated
if min is None and max is None: | ||
raise ValueError("One of max or min must be given") | ||
elif min is None: | ||
return um.clip_above(a, max, out=out, casting=casting) |
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.
Can we not use um.minimum
here? (and um.maximum
instead of clip_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.
Nope - clip needs to preserve NaNs in and only in the first argument. maximum always propagates, and fmax always ignores. So we need a third maximum-like function
'clip', | ||
) | ||
|
||
if name[0] != '_' and name not in skip: | ||
# matmul is special, it does not use the OUT_SCALAR replacement strings |
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.
Need to adjust the comment here on why clip
is excluded; though perhaps better to put it behind each item in skip
.
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.
Can you still move this comment up to the definition of skip
?
Taking the conversation of using
Looking at the code, I see this is because for array-like min and max, the My sense would be to keep this behaviour, following the maxim that in case of doubt one should refuse the temptation to guess: the user should be Note that if we felt it was needed, we could keep this completely backwards compatible if in the wrapping code we checked for cases of scalar |
Not really - I just noticed that in the past someone complained when the
That's a fairly strong argument I hadn't thought of as to why the nan behavior is useless. Unfortunately the replacement is quite a bit more verbose.
|
@eric-wieser - #7601 complained that Here, remember that at present My own sense is to always propagate |
Given that the current nan behavior is inconsistent and depends on things like the byte order, I think we just drop this without a deprecation warning:
|
OK, makes sense to just have it in the release notes. So, we change to always behave consistently with |
4989ee1
to
375f443
Compare
1a30542
to
add2e0c
Compare
Needs rebase. Test failure is fixed in master. |
Needs rebase. Test error is fixed in master. |
This includes: * The addition of 3-input PyObject inner loop * The removal of `->f->fastclip` for builtin types, which now use ufuncs instead * A deprecation in `PyArray_Clip` for third-party types that still use `->f->fastclip` * A deprecation of the unusual casting behavior of `clip` * A deprecation of the broken `nan`-behavior of `clip`, which was previously dependent on dimensionality and byte-order.
* Unit test for object clip issue * parametrized test_simple_int32_inout() to additionally handle scenario where "unsafe" casting is explicitly passed through, as requested by reviewer * add a requested comment related to possibility of future nan check optimization for `@name@_clip` * add a unit test to cover the case where np.clip() is called with None for both max and min * add a unit test for the case where out is None and casting is specified as an invalid value, to flush through code path in TestClip.fastclip * add unit test + doc update for expected behavior when amin > amax * add unit test + patch for bug in npy_ObjectClip; its operations and operands were wrong; the unit test case is based on a scenario probed by the hypothesis library * add unit test for error in timedelta64 MAX function for clip handling * add unit test for a pathological case where np.ones(10) is clipped with amin=1, amax=0
This changes the object array behavior to match the other behavior
rebased / force pushed -- if CI is all green I plan to merge as noted above |
The CI failures are from things like This is presumably coming in from work by @r-devulap and @juliantaylor? Hopefully no merge conflict in release notes arises while waiting for this to get resolved / rebased. |
I think the reason you are seeing that error is the file |
Is there a reason why |
Perhaps we can make that refinement if the inclusion is not needed @eric-wieser ? |
I was able to build without |
Thanks, that's helpful feedback! Eric or Marten can probably confirm the safety of removal, but sounds straightforward. |
I was under the impression that some of the macros in that file expand to things from the simd header. I think adding inline is the right way to go here. |
* ISA_exp/log have been inlined to prevent build errors when included in PR 12519
Ok, I inlined the low-level exp / log stuff & local test suite results are unchanged while the build warnings-turned-errors disappear. Hopefully CI agrees. |
Thanks Eric and all reviewers. Merging with fingers crossed based on various discussions above. |
This includes:
->f->fastclip
for builtin types, which now use ufuncs insteadPyArray_Clip
for third-party types that still use->f->fastclip
clip
nan
-behavior ofclip
, which was previously dependent on dimensionality and byte-order.max < min
which brings object arrays in line with the other typesSurprisingly, this actually seems to have better performance (N=10000):
Edit: those performance numbers are probably not representative of the wrapped call - there is a big cost to pay for the deprecations.