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

Feature request: Allocations on outlined iteration #56587

Open
jakobnissen opened this issue Nov 17, 2024 · 1 comment
Open

Feature request: Allocations on outlined iteration #56587

jakobnissen opened this issue Nov 17, 2024 · 1 comment
Labels
compiler:optimizer Optimization passes (mostly in base/compiler/ssair/) feature Indicates new feature / enhancement requests

Comments

@jakobnissen
Copy link
Contributor

jakobnissen commented Nov 17, 2024

I've noticed that a big part of the allocations in my Julia code come from Base.iterate, when it doesn't inline. That might be a possible target of optimisation - at least I see no reason it couldn't stack-allocate it.

Here is a small example:

julia> struct ViewIterator{T}
           x::T
       end

julia> @noinline function Base.iterate(x::ViewIterator, i::Int=1)
           i > length(x.x) ? nothing : (@inbounds view(x.x, i:i), i+1)
       end

julia> function foo(x::Vector{Int})
           n = 0
           for i in ViewIterator(x)
               n += @inbounds i[1]
           end
           n
       end
foo (generic function with 1 method)

julia> v = rand(Int, 1000000);

julia> @time foo(v)
  0.124638 seconds (1000.00 k allocations: 61.035 MiB, 89.47% gc time)
-754608176331557632

These allocations appear to come from the Union{Tuple{SubArray, Int}, Nothing} return value of iterate. Interestingly, it's not that having a non-inlined function return SubArray itself heap allocates - if we change the code like so, it allocates the result on the stack:

julia> @noinline bar(x, i) = @inbounds view(x, i:i);

julia> function foo(x::Vector{Int})
           n = 0
           for i in 1:length(x)
               n += @inbounds bar(x, i)[1]
           end
           n
       end;

julia> @time foo(v)
  0.002680 seconds
7211620882627564191

So, something causes the small union to heap-allocate, whereas the subarray can stack allocate.

@jakobnissen jakobnissen added compiler:optimizer Optimization passes (mostly in base/compiler/ssair/) feature Indicates new feature / enhancement requests labels Nov 17, 2024
@gbaraldi
Copy link
Member

gbaraldi commented Nov 18, 2024

This requires an ABI improvement. Something like #55045 is trying to do. This is the same thing as #53584

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler:optimizer Optimization passes (mostly in base/compiler/ssair/) feature Indicates new feature / enhancement requests
Projects
None yet
Development

No branches or pull requests

2 participants