-
Notifications
You must be signed in to change notification settings - Fork 153
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
specialize axes(S, dim) to return SOneTo #916
base: master
Are you sure you want to change the base?
Conversation
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.
Thanks, this looks like a good idea.
Gentle bump |
I'd prefer to have a second opinion here before merging this -- if the axis number isn't constant-propagated, this might be considered a less desirable behavior than the current one. |
For reference, the behavior of julia> using StrideArrays, Static, ArrayInterface
julia> A = @StrideArray rand(10, 10);
julia> B = @StrideArray rand(8, 10);
julia> ArrayInterface.axes(A,1)
Base.OneTo(static(10))
julia> ArrayInterface.axes(B,1)
Base.OneTo(8)
julia> ArrayInterface.axes(B,StaticInt(1))
Base.OneTo(static(8))
julia> ArrayInterface.axes(B,StaticInt(2))
Base.OneTo(static(10)) For So one possibility is to return an |
Good point, restricting this to arrays where all axes have the same length removes the issue with type stability. |
The top message's case is for julia> ArrayInterface.axes(A,3) |> dump
ArrayInterface.OptionallyStaticUnitRange{StaticInt{1}, StaticInt{1}}
start: StaticInt{1} static(1)
stop: StaticInt{1} static(1)
julia> ArrayInterface.axes(A,2) |> dump
Base.OneTo{StaticInt{10}}
stop: StaticInt{10} static(10) I have a vague memory that this PR grew out of thinking about |
Yes indeed, this came out of Using the nightly build, julia> @code_warntype axes(a, 1)
MethodInstance for axes(::SMatrix{1, 2, Int64, 2}, ::Int64)
from axes(A::AbstractArray{T, N}, d) where {T, N} in Base at abstractarray.jl:72
Static Parameters
T = Int64
N = 2
Arguments
#self#::Core.Const(axes)
A::SMatrix{1, 2, Int64, 2}
d::Int64
Body::Union{SOneTo{1}, SOneTo{2}, Base.OneTo{Int64}}
1 ─ nothing
│ %2 = Core.typeassert(d, Base.Integer)::Int64
│ %3 = (%2 <= $(Expr(:static_parameter, 2)))::Bool
└── goto #3 if not %3
2 ─ %5 = Base.axes(A)::Core.Const((SOneTo(1), SOneTo(2)))
│ %6 = Base.getindex(%5, d)::Union{SOneTo{1}, SOneTo{2}}
└── return %6
3 ─ %8 = Base.OneTo(1)::Core.Const(Base.OneTo(1))
└── return %8
This PR julia> @code_warntype axes(a, 1)
MethodInstance for axes(::SMatrix{1, 2, Int64, 2}, ::Int64)
from axes(s::StaticArray, d) in StaticArrays at /home/jishnu/Dropbox/JuliaPackages/StaticArrays.jl/src/abstractarray.jl:15
Arguments
#self#::Core.Const(axes)
s::SMatrix{1, 2, Int64, 2}
d::Int64
Body::Union{SOneTo{1}, SOneTo{2}}
1 ─ %1 = StaticArrays.ndims(s)::Core.Const(2)
│ %2 = (d <= %1)::Bool
└── goto #3 if not %2
2 ─ %4 = StaticArrays.Size(s)::Core.Const(Size(1, 2))
│ %5 = StaticArrays._axes(%4)::Core.Const((SOneTo(1), SOneTo(2)))
│ %6 = Base.getindex(%5, d)::Union{SOneTo{1}, SOneTo{2}}
└── return %6
3 ─ %8 = Core.apply_type(StaticArrays.SOneTo, 1)::Core.Const(SOneTo{1})
│ %9 = (%8)()::Core.Const(SOneTo(1))
└── return %9 The return type inferred is narrower in this case (as certain axes have the same type as the trivial ones). In general on master julia> @code_warntype axes(a, 1)
MethodInstance for axes(::SMatrix{3, 2, Int64, 6}, ::Int64)
from axes(A::AbstractArray{T, N}, d) where {T, N} in Base at abstractarray.jl:72
Static Parameters
T = Int64
N = 2
Arguments
#self#::Core.Const(axes)
A::SMatrix{3, 2, Int64, 6}
d::Int64
Body::Union{SOneTo{3}, SOneTo{2}, Base.OneTo{Int64}}
1 ─ nothing
│ %2 = Core.typeassert(d, Base.Integer)::Int64
│ %3 = (%2 <= $(Expr(:static_parameter, 2)))::Bool
└── goto #3 if not %3
2 ─ %5 = Base.axes(A)::Core.Const((SOneTo(3), SOneTo(2)))
│ %6 = Base.getindex(%5, d)::Union{SOneTo{3}, SOneTo{2}}
└── return %6
3 ─ %8 = Base.OneTo(1)::Core.Const(Base.OneTo(1))
└── return %8 This PR julia> @code_warntype axes(a, 1)
MethodInstance for axes(::SMatrix{3, 2, Int64, 6}, ::Int64)
from axes(s::StaticArray, d) in StaticArrays at /home/jishnu/Dropbox/JuliaPackages/StaticArrays.jl/src/abstractarray.jl:15
Arguments
#self#::Core.Const(axes)
s::SMatrix{3, 2, Int64, 6}
d::Int64
Body::Union{SOneTo{3}, SOneTo{2}, SOneTo{1}}
1 ─ %1 = StaticArrays.ndims(s)::Core.Const(2)
│ %2 = (d <= %1)::Bool
└── goto #3 if not %2
2 ─ %4 = StaticArrays.Size(s)::Core.Const(Size(3, 2))
│ %5 = StaticArrays._axes(%4)::Core.Const((SOneTo(3), SOneTo(2)))
│ %6 = Base.getindex(%5, d)::Union{SOneTo{3}, SOneTo{2}}
└── return %6
3 ─ %8 = Core.apply_type(StaticArrays.SOneTo, 1)::Core.Const(SOneTo{1})
│ %9 = (%8)()::Core.Const(SOneTo(1))
└── return %9 The type-instability is similar in both master and in this PR. |
Close #52373, or at least the part that may be addressed here. After this, the first axis for an `Adjoint(parent::AbstractVector)` will be the second axis of the `parent`. This will change the type of the axis where the parent array type specializes `axes(A, d)`. In the short term, this would improve type-stability in cases such as ```julia julia> A = OffsetArray([1,2], 2); julia> @code_typed axes(A')[1] CodeInfo( 1 ─ %1 = $(Expr(:boundscheck))::Bool │ %2 = Base.getfield(t, i, %1)::OffsetArrays.IdOffsetRange{Int64, Base.OneTo{Int64}} └── return %2 ) => OffsetArrays.IdOffsetRange{Int64, Base.OneTo{Int64}} ``` where the result is now concretely inferred instead of being a small `Union`. In principle, with JuliaArrays/StaticArrays.jl#916, this would make the axes of the adjoint of a `StaticVector` statically sized.
Currently
After this PR
As a consequence,
returns a
StaticArray