-
-
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
avoid intermediate map allocations in multi-arg mapreduce #55301
base: master
Are you sure you want to change the base?
Conversation
Now that the mapreduce infrastructure (mostly) supports broadcasted objects, we can use a lazy Broadcasted on array-likes instead of using an intermediate `map`. This exercises the internals more thoroughly and identifies a few more places where we need to use `::AbstractArrayOrBroadcasted` and requires an offset axis bugfix.
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 change on mapreduce is a broken one as map(f, c...)
has no length constraint if ndims
of inputs are 1
julia> mapreduce(+, +, 1:3, 1:2) == mapreduce(+, +, 1:2, 1:2)
true
But the rest seems good though, see also #41054.
😭 Ooof, this is why we can't have nice things. Pretty wildly, this behavior doesn't look to be tested. I could've sworn we had an absurdly long megathread on this (mis)feature, but I can't find it at the moment. It is documented in the generic
But for the specific method I'm changing here, there's a slightly different spec:
I suppose the easy answer is just fall back to the allocating |
I think I added the documentation at some point to match the reality... which IIRC was added basically by accident in 1.5, and had no tests for ages. On 1.0 julia> VERSION
v"1.0.5"
julia> map(+, 1:2, 1:3)
ERROR: DimensionMismatch("dimensions must match") |
Yeah, but the iterator version has done it "forever": julia> VERSION
v"1.0.5"
julia> map(+, Iterators.drop(1:5, 1), Iterators.drop(1:5, 2))
3-element Array{Int64,1}:
5
7
9 It's somewhat related to #46707, but I still can't find the discussion I was thinking of. |
this now matches the documentation, but still is not *exactly* the previous behavior
So this is still slightly more restrictive than what we had before. Let's see what Nanosoldier says: @nanosoldier runtests() |
@nanosoldier |
reduce(op, map(f, A, B...); kw...) | ||
function mapreduce(f, op, A::AbstractArrayOrBroadcasted, B::AbstractArrayOrBroadcasted...; kwargs...) | ||
Adims = ndims(A) | ||
if any(b->Adims != ndims(b), B) |
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.
if any(b->Adims != ndims(b), B) | |
if Adims != 1 && any(b->Adims != ndims(b), B) |
return reduce(op, map(f, A, B...); kwargs...) | ||
end | ||
Aax = axes(A) | ||
all(b->Aax==axes(b), B) || throw(ArgumentError("all arguments must have the same axes")) |
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.
Perhaps DimensionMismatch
is better than ArgumentError
here?
@@ -87,7 +94,7 @@ end | |||
|
|||
# initialization when computing minima and maxima requires a little care | |||
for (f1, f2, initval, typeextreme) in ((:min, :max, :Inf, :typemax), (:max, :min, :(-Inf), :typemin)) | |||
@eval function reducedim_init(f, op::typeof($f1), A::AbstractArray, region) | |||
@eval function reducedim_init(f, op::typeof($f1), A::AbstractArrayOrBroadcasted, region) |
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 change seems incomplete as view
in L106 has no Broadcasted
support.
we might need
reduced_view(A::AbstractArray, ri) = view(A, ri...)
reduced_view(bc::Broadcasted, ri) = Broadcasted(bc.style, bc.f, bc.args, ri)
The package evaluation job you requested has completed - possible new issues were detected. |
I'll put this on hold for now — #55318 will unblock the hard part here. |
Now that the mapreduce infrastructure (mostly) supports broadcasted objects, we can use a lazy Broadcasted on array-likes instead of using an intermediate
map
. This exercises the internals more thoroughly and identifies a few more places where we need to use::AbstractArrayOrBroadcasted
and requires an offset axis bugfix.Fixes #38558
local benchmarks
Alternative to: #41001 (cc @mcabbott)
Fixes #53417
more benchmarking from 53417