-
-
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
More efficient mapreduce(f, op, A, B, C; init)
#41001
base: master
Are you sure you want to change the base?
Conversation
_mapreduce_dim_vararg(f, op, init, As::Tuple, dims) = | ||
_mapreduce_dim_vararg(f, op, init, As, dims, IteratorSize(Generator(f, As...))) |
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 only purpose of Generator(f, As...)
is for the traits HasShape
etc. Perhaps there's a better way.
Some weird test cases:
mapreduce(/,+,[1 2 3; 4 5 6],[7,8,9,10],dims=2,init=0.0)
mapreduce(/,+,[1 2 3; 4 5 6],[7,8,9,10],dims=1,init=0.0)
mapreduce(/,+,[1 2 3; 4 5 6],rand(2,3,1),dims=1,init=0.0)
mapreduce(/,+,rand(2,3),rand(2,3,1),dims=2,init=0.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.
A bolder possibility would be to declare those to be errors. This would fit with restricting map(f, A, B)
to size(A)==size(B)
, instead of this zip
behaviour. For tuples, this is still how map
acts; in the discussion at #42216 most people seem to prefer that to the zip
.
_mapreduce_dim_vararg(f, op, init, As::Tuple, ::Colon) = | ||
only(_mapreduce_dim_vararg(f, op, init, As, 1:maximum(ndims, As))) |
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.
What I've called _mapreduce_dim_vararg
could simply be methods of _mapreduce_dim
. It would be tidiest to re-order its arguments from _mapreduce_dim(f, op, init, A, dims)
to _mapreduce_dim(f, op, init, dims, A, Bs...)
. Would this be acceptable?
According to https://juliahub.com/ui/Search?q=_mapreduce_dim&type=code there are 3 packages which overload _mapreduce_dim
, so perhaps it's not a disaster to change it.
# vararg version | ||
@noinline function mapreduce_impl(f::F, op, A::AbstractArrayOrBroadcasted, | ||
ifirst::Integer, ilast::Integer, blksize::Int, | ||
Bs::Vararg{AbstractArrayOrBroadcasted,N}) where {F,N} | ||
Xs = (A, Bs...) | ||
if ifirst == ilast | ||
@inbounds x1 = ith_all(ifirst, Xs) |
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 could be combined with the original version? It is a bit of an ugly signature, mapreduce_impl(f, op, A, i,j,b, Bs...)
; not sure how hard it would be to change that to put all the arrays last.
is this ready to merge? |
I believe it works, but it's quite a thicket of functions, and it's possible that someone who knows it better may prefer a different approach. For instance, If we do want this approach, I highlighted places above where I wasn't sure this was the best choice of signature. |
As I understand it, this isn't valid since |
It might be easy to first check for cases broadcasting allows and map does not (like extending dimensions). Cases where map stops early like |
Fuse |
This reverts commit e0ed9e3.
This is an attempt to make at least some cases of
mapreduce(f, op, A, B C)
faster. At present all cases just callreduce(op, map(f, A, B C))
.This PR generalises
_mapreducedim!
to allow several arrays, which is enough to make reductions withinit
fast. Wheninit
is not given, generalisingreducedim_init
looks delicate & largely orthogonal, so is left for future work.For the case of scalar reductions, it appears to be faster to call
only(_mapreducedim!(...))
wheninit
is given. Wheninit
is not given, it useszip
exactly as in #39053. That isn't as fast, it saves memory but not always time compared to existingreduce(op, map(f, ...
. More could be done here too.Times, with
dims
:Times, scalar reduction:
Times on the example from #38558, on my computer:
I haven't checked tests closely, nor thought about whether more are needed.