Repository navigation
Add fast path to stack(::AbstractVectorOfArray) for numeric inner arrays - #671
Draft
ChrisRackauckas-Claude wants to merge 1 commit into
Draft
ChrisRackauckas-Claude wants to merge 1 commit into
ChrisRackauckas-Claude wants to merge 1 commit into
Conversation
stack(VA) called stack(stack.(VA.u); dims): the inner stack.() applies
stack to every element of VA.u before the outer stack sees them. That
step exists to collapse nested AbstractVectorOfArray (or other
non-plain-array) elements into plain arrays first, but when VA.u's
elements are already plain numeric arrays, stack.() is a redundant
elementwise copy — one extra allocation per inner array for no change
in the result.
Skip it when eltype(VA.u) <: AbstractArray{<:Number} and stack VA.u
directly; fall back to the original stack(stack.(VA.u); dims) path for
everything else (nested AbstractVectorOfArray elements, etc.), so that
case is unaffected.
n=1000 inner arrays: 28.4us/2006 allocs -> 5.6us/3 allocs (1.12),
52.2us/1002 allocs (1.10, unmeasured after since the audit reported
"same on 1.10" was not re-verified for this specific candidate; the
allocation drop alone (104160 -> 16088 bytes) is confirmed on 1.10).
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Agent-Harness: Claude Code 2.1.294
Agent-Model: claude-sonnet-5
Agent-Session: https://claude.ai/code/session_01LPHREnnonfLg1VcE1EJovv
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed and why
Base.stack(VA::AbstractVectorOfArray; dims)was implemented asstack(stack.(VA.u); dims). The innerstack.(VA.u)broadcastsstackover every element ofVA.ubefore the outerstackruns — this exists to collapse a nestedAbstractVectorOfArray(or other non-plain-array) inner element into a plain array first. WhenVA.u's elements are already plain numeric arrays, that innerstack.()call does nothing useful:stackon a plain numeric array just returns an equivalent copy, so it's purely a wasted allocation per inner array.Added a fast path: when
eltype(VA.u) <: AbstractArray{<:Number}, callstack(VA.u; dims)directly. Otherwise (e.g. nestedAbstractVectorOfArrayelements), fall back to the originalstack(stack.(VA.u); dims)unchanged.Before/after
n = 1000innerVector{Float64}of length 2:(the 16088-byte "after" allocation on 1.12 is just the final 2×1000
Float64output matrix — 16000 bytes of data plus a small header; nothing else is allocated)Correctness: plain-numeric
stackresult is identical to before (stack(testva) == [1 4 7; 2 5 8; 3 6 9]etc.,dimskwarg unaffected). The nested case (VA[VA[ones(2,2), 2ones(2,2)], 3ones(2,2,2)], an existing test ininterface_tests.jl) still goes through the unmodified fallback path and is unaffected.Failing-before / passing-after
Added to
test/Core/interface_tests.jl, right after the existingstacktests:Before (reverted
src/vector_of_array.jlto unmodified master, kept the new test):After (this branch):
test/Core/interface_tests.jlruns to completion with no failures, on both Julia 1.10.12 and 1.12.7.Full
GROUP=Corerun (both Julia versions): all testsets green, including the existing non-numeric/nestedstacktest.GROUP=QAon 1.12.7: 20/20 pass.GROUP=QAon 1.10.12 hits the same pre-existing, unrelatedAquaambiguity failure documented in #667 (confirmed present on unmodified master).What was not verified
stackon GPU-backed inner arrays was not benchmarked (eltype(VA.u) <: AbstractArray{<:Number}is satisfied for e.g.CuArray/JLArrayelements too, so the fast path would apply there, but this wasn't measured on a GPU backend).Anything a reviewer should push back on
stacktests.Please ignore until reviewed by @ChrisRackauckas.
Risk assessment
src/vector_of_array.jl, onestackmethod. No public API signature change, no behavior change for any input (fast path produces the identical result to the fallback, verified).GROUP=Corefull pass on Julia 1.10 and 1.12, including the pre-existing nested-AbstractVectorOfArraystack test (unaffected, goes through the unchanged fallback).🤖 Generated with Claude Code
https://claude.ai/code/session_01LPHREnnonfLg1VcE1EJovv