Skip to content
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

[WIP] faster reductions #659

Merged
merged 3 commits into from
Sep 26, 2019

Conversation

mateuszbaran
Copy link
Collaborator

I think this is the simplest possible solution for #540 . This essentially avoids passing around keyword arguments in some common use cases. I'll change other reduce-like functions if you think it's a good solution.

@coveralls
Copy link

coveralls commented Sep 20, 2019

Coverage Status

Coverage decreased (-0.05%) to 81.535% when pulling d3623b9 on mateuszbaran:mbaran/faster-reduction into 935dc85 on JuliaArrays:master.

Copy link
Member

@c42f c42f left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll change other reduce-like functions if you think it's a good solution.

Please do, this looks like a clean solution 👍

src/mapreduce.jl Outdated
@inline reduce(op, a::StaticArray; kw...) = mapreduce(identity, op, a; kw...)
@inline reduce(op, a::StaticArray; dims=:, kw...) = _reduce(op, a, dims, kw.data)

@inline _reduce(op, a::StaticArray, dims=:, kw::NamedTuple=NamedTuple()) = _mapreduce(identity, op, dims, kw, Size(a), a)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this reduce doesn't need the dims=: default because it's internal?

@mateuszbaran
Copy link
Collaborator Author

Variants with default value of dims work nicely now but when its specified it's still hopelessly slow. I'll investigate it.

@mateuszbaran
Copy link
Collaborator Author

OK, the problem is that if you call for example any(m, dims=1) constant keyword argument dims is not properly propagated and serious type instability happens. It's still fast when using any(m, dims=Val(1)). AFAICT any(m, dims=1) can't easily be made fast in general but it's possible to hardcode a few dims like 1 and 2 in _mapreduce(f, op, D::Int, nt::NamedTuple, sz::Size{S}, a::StaticArray) to make them fast. Do you care about it?

@c42f c42f added bugfix performance runtime performance labels Sep 25, 2019
@c42f
Copy link
Member

c42f commented Sep 25, 2019

it's possible to hardcode a few dims like 1 and 2 in _mapreduce

You mean a pattern something like

if D == 1
    _mapreduce(f, op, Val(1), nt, sz, a)
elseif D == 2
    _mapreduce(f, op, Val(2), nt, sz, a)
...

?

If that's what it takes to avoid a massive and surprising performance cliff I think it's worthwhile (just add a comment to explain the hack).

@mateuszbaran
Copy link
Collaborator Author

Yes, exactly that. I'll make the change then.

@mateuszbaran
Copy link
Collaborator Author

I've changed that part, although I'm not completely sure why it makes such a difference since that method of _mapreduce still isn't type stable.

julia> m = SArray{Tuple{3,3,3,3}}(rand(Bool, 3,3,3,3));

julia> using BenchmarkTools

julia> f1(x) = any(x, dims=1)
f1 (generic function with 1 method)

julia> f4(x) = any(x, dims=4)
f4 (generic function with 1 method)

julia> @benchmark f1($m)
BenchmarkTools.Trial: 
  memory estimate:  48 bytes
  allocs estimate:  1
  --------------
  minimum time:     39.845 ns (0.00% GC)
  median time:      40.340 ns (0.00% GC)
  mean time:        51.146 ns (17.98% GC)
  maximum time:     53.062 μs (99.91% GC)
  --------------
  samples:          10000
  evals/sample:     991

julia> @benchmark f4($m)
BenchmarkTools.Trial: 
  memory estimate:  160 bytes
  allocs estimate:  3
  --------------
  minimum time:     4.566 μs (0.00% GC)
  median time:      4.687 μs (0.00% GC)
  mean time:        4.720 μs (0.00% GC)
  maximum time:     12.804 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     7

@c42f
Copy link
Member

c42f commented Sep 26, 2019

Yes that seems a bit mysterious.

It looks like (maybe) Core.kwfunc(Main.any) doesn't get the inline meta inherited from its body, so that would be something to fix in Base I guess.

@KristofferC
Copy link
Contributor

Feels a bit like JuliaLang/julia#30411.

@c42f
Copy link
Member

c42f commented Sep 26, 2019

Yes, that seems likely to be the same underlying issue: lowering producing some extra method definitions which don't respect whatever Expr(:meta) are attached in the surface syntax.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugfix performance runtime performance
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants