-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Fix length calculation of broadcast over tuples #23887
Conversation
base/broadcast.jl
Outdated
@@ -127,6 +127,7 @@ end | |||
end | |||
|
|||
Base.@propagate_inbounds _broadcast_getindex(A, I) = _broadcast_getindex(containertype(A), A, I) | |||
Base.@propagate_inbounds _broadcast_getindex(::Type{Tuple}, A::Tuple{Any}, I) = A[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.
Should A[1]
not be A[I]
?
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.
No, you can see that there is a ::Tuple{Any}
in the signature, we need this for handling cases like (1,2,3) .+ (1,)
. This shouldn't be a problem as we want (x,)
where x
is a scalar to behave the same as [x]
or x
.
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 missed the Any
last night :). To make this method's purpose clearer, perhaps add a comment or an adjacent general method
Base.@propagate_inbounds _broadcast_getindex(::Type{Tuple}, A::Tuple, I) = A[I]
though it would be redundant with
Base.@propagate_inbounds _broadcast_getindex(::Any, A, I) = A[I]
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.
I have added a comment.
Yes, rather I was wondering whether the simpler former logic could be improved while remaining simpler than that in this pull request. A few comments describing the logic in this pull request would do the trick as well :). Best! |
7890971
to
332dbaa
Compare
I couldn't come up with a simpler approach, but I have added comments as you suggested. The wording could probably be improved, so if you have any suggestions about it, I'm all ears. |
332dbaa
to
893dfa2
Compare
base/broadcast.jl
Outdated
# When the result of broadcast is a tuple it can only come from mixing n-tuples | ||
# of the same length with scalars and 1-tuples. So, in order to have a | ||
# type-stable broadcast we need to find a tuple of maximum length (except when | ||
# there are only scalars empty tuples and empty tuples, in which case the |
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.
One too many "empty tuples?"
💯 for the comments! :) |
893dfa2
to
8049df1
Compare
Because of a possible mess with ambiguities, I decided to use the |
Has anyone have more comments/objections? If not I'd like to merge this in a day or two. |
_tuplebroadcast_maxtuple(containertype(A), containertype(B), A, B) | ||
@inline tuplebroadcast_maxtuple(A, Bs...) = | ||
tuplebroadcast_maxtuple(A, tuplebroadcast_maxtuple(Bs...)) | ||
tuplebroadcast_maxtuple(A::NTuple{N,Any}, ::NTuple{N,Any}...) where {N} = A |
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 think this needs to be a _tuplebroadcast_maxtuple
method, for example with the testcase broadcast(+, (1, 2), (3, 4), 5)
.
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.
That example works with this PR as is. I had it like this to reduce the compiler/inference work in cases where you have a bunch of tuples of the same length and a scalar element (which I imagined would be common), e.g. (1,2) .+ (2,3) .+ (3,4) .+ (4,5) .+ 1
. But I can make it a _tuplebroadcast_maxtuple
for consistency if preferred.
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.
Sorry, I screwed up the order of my example. It should be broadcast(+, 5, (1, 2), (3, 4))
which I believe would not currently work.
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 can confirm that example (or broadcast(+, (1, 2), 5, (3, 4))
) works fine.
tuplebroadcast_maxtuple
will call _tuplebroadcast_maxtuple
only when the number of arguments to tuplebroadcast_maxtuple
is two and both are not tuples of the same length (if they are, dispatch would select tuplebroadcast_maxtuple(A::NTuple{N,Any}, ::NTuple{N,Any}...) where {N}
instead).
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.
Oh, I understand. Thanks for the correction.
Wouldn't a method for two tuples of the same length be necessary anyway? This method can be kept as a specialization, right? |
In case it's of interest, #23939 has a |
Yes a method for tuples of the same length is necessary. And the current one could be changed into a
Thanks Tim, I don't think both behave the same (but that PR is really nice, I'm going to take a closer look into it). |
@nanosoldier |
Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @ararslan |
@nanosoldier |
Your benchmark job has completed - no performance regressions were detected. A full report can be found here. cc @ararslan |
Good to go? |
@pabloferz Please confirm the behavior of |
@TotalVerb the behaviour of broadcast for the examples you have mentioned seems to be the expected with this PR. |
(cherry picked from commit 698ef27)
(cherry picked from commit 698ef27)
(cherry picked from commit 698ef27)
(cherry picked from commit 698ef27)
(cherry picked from commit 698ef27)
(cherry picked from commit 698ef27)
(cherry picked from commit 698ef27)
(cherry picked from commit 698ef27)
Fixes #23647