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

Give access to non-allocating combinations iterator #73

Merged
merged 1 commit into from
Oct 12, 2018

Conversation

mschauer
Copy link
Member

@mschauer mschauer commented Sep 25, 2018

This gives access to the non-allocating Combinations internals such that e.g. a copy of the changing state can be made with SVector.

Old:

julia> @btime collect(combinations(1:50,5))
  883.211 ms (8475043 allocations: 695.09 MiB)

julia> function f()
           i = 0
           for c in combinations(1:50, 5)
               i = i + c[1]
           end
           i
       end
f (generic function with 1 method)

julia> @btime f()
  1.079 s (8475041 allocations: 678.92 MiB)
18009460

New:

julia> @btime collect(combinations(1:50,5))
  303.784 ms (6356283 allocations: 404.12 MiB)

julia> @btime f()
  246.004 ms (6356281 allocations: 387.96 MiB)
18009460

julia> function g()
           i = 0
           for c in Combinatorics.Combinations(50, 5)
               i = i + c[1]
           end
           i
       end
g (generic function with 1 method)

julia> @btime g()
  71.276 ms (2118761 allocations: 64.66 MiB)
18009460

julia> @btime map(SVector{5,Int},Combinatorics.Combinations(50,5))
  100.676 ms (2118764 allocations: 145.48 MiB)

Actually, I do not see why it should still allocate in each iteration in g, maybe you see something or one should sprinkle some inbounds.

@mschauer mschauer merged commit 0129280 into JuliaMath:master Oct 12, 2018
@mschauer mschauer mentioned this pull request Oct 15, 2018
@Moelf
Copy link

Moelf commented Nov 9, 2022

why does it still allocate 😭 in each iteration

@mschauer
Copy link
Member Author

Does it still?

@Moelf
Copy link

Moelf commented Nov 10, 2022

julia> function f(N)
           for c in Combinations(N, 4)
           end
       end
f (generic function with 1 method)

julia> @benchmark f(10)
BenchmarkTools.Trial: 10000 samples with 9 evaluations.
 Range (min  max):  2.305 μs  142.252 μs  ┊ GC (min  max): 0.00%  96.89%
 Time  (median):     2.609 μs               ┊ GC (median):    0.00%
 Time  (mean ± σ):   2.851 μs ±   4.948 μs  ┊ GC (mean ± σ):  6.16% ±  3.49%

  ▃▅▅▃▁▁▅▇█▇▅▂                            ▁▂▂▂                ▂
  █████████████▇██▇██▇▆▆▅▅▁▄▄▃▃▃▄▃▁▄▃▁▄▆▇██████▆▅▁▅▄▅▅▄▄▁▅▆▇█ █
  2.31 μs      Histogram: log(frequency) by time      4.43 μs <

 Memory estimate: 6.66 KiB, allocs estimate: 211.

julia> @benchmark f(20)
BenchmarkTools.Trial: 10000 samples with 1 evaluation.
 Range (min  max):  48.622 μs   1.510 ms  ┊ GC (min  max): 0.00%  95.13%
 Time  (median):     53.622 μs              ┊ GC (median):    0.00%
 Time  (mean ± σ):   58.645 μs ± 82.108 μs  ┊ GC (mean ± σ):  7.96% ±  5.47%

  ▄▆▄▂▁ ▅█▇▅▃▁▁                                               ▂
  ██████████████▇▇▇▇▆▆▅▄▃▁▁▁▁▁▁▁▁▁▁▁▁▃▃▁▁▁▁▃▄▁▁▃▃▅▆█▇▇▅▄▃▅▇██ █
  48.6 μs      Histogram: log(frequency) by time      86.9 μs <

 Memory estimate: 151.50 KiB, allocs estimate: 4846.

notice the capital Combination, I use it combined with @view in reality

@mschauer
Copy link
Member Author

The iterator state is a vector or nothing, I don't know if small unions with vectors can be stack allocated.

@Moelf
Copy link

Moelf commented Nov 10, 2022

isn't the problem this line always heap allocate?

comb = [c.a[si] for si in s]

@mschauer
Copy link
Member Author

Can you check if #125 helps for your use case?

@Moelf
Copy link

Moelf commented Nov 10, 2022

yep, it does help with the above toy example.

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

Successfully merging this pull request may close these issues.

2 participants