-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
RFC: Make strides
into a generic trait
#30432
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.
Using nothing
as the default here is interesting. On balance I think this is a good way to go.
stride(A::AbstractArray, k::Integer) = strides(A)[k] | ||
function stride(A::AbstractArray, k::Integer) | ||
str = strides(A) | ||
if str === nothing |
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.
More compact, if desired:
return str === nothing ? nothing : str[k]
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.
The existing function allows k>ndims(A)
, like stride([1,2,3], 99) == 3
.
# provide strides, but only for eltypes that are directly stored in memory (i.e. unaffected | ||
# by recursive `adjoint` and `transpose`, being `Real` and `Number` respectively) | ||
function Base.strides(a::Union{Adjoint{<:Real, <:AbstractVector}, Transpose{<:Number, <:AbstractVector}}) | ||
str = strides(a.parent) |
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.
Use A
and strides(parent(A))
?
Clever, clever, clever. So instead of having a separate trait hierarchy of storage types, we just pass In other words, this makes me think that Now, I don't think a function from index -> storage is the right concept here… what is the right concept? Is there one? Am I going off the deep end? |
Nice idea, Matt. That’s some next level stuff! @dlfivefifty I think the point is that there would be functions of different types returned by |
I get that. I just don't see how it would work in dispatch with composed layouts like But conflating memory layout with
struct StridedApplyStyle{F<:Function, ST<:Tuple} <: ApplyStyle
f::F
strides::ST
end
ApplyStyle(::typeof(*), A::AbstractArray...) = StridedApplyStyle(*, strides.(A)) as the type that determines the apply style from the strides. |
Right - we’ll definitely need a “promotion” mechanism to control dispatch of operations on multiple containers. |
+1 |
What is the status on this? |
Just a note that our potential design space just got significantly larger with #34126 — we no longer need to be fearful of holding onto arrays in structs. |
Triage likes this. How much work is needed to merge? |
Returns `nothing` for non-strided arrays, otherwise gives the give strides in memory. Useful as an extensible trait in generic contexts, and simpler to overload for cases of "wrapped" arrays where "stridedness" can be deferred to the parent rather than a complex (and inextensible) method signature.
315964a
to
532aebd
Compare
I have rebased this and update
It's been such a long time and I haven't been following the changes closely - does anyone else know if more should be done? |
My take on a pathway for replacing
StridedArray
with a more generic and extensible trait. This simply makes thestrides
function a bit more generic, but does not rearrange any of the dispatch patterns aroundStridedArray
or anything like that.Returns
nothing
for non-strided arrays, otherwise gives the strides in memory. Useful as an extensible trait in generic contexts and for arranging dispatch patterns, and simpler to overload for cases of "wrapped" arrays where "stridedness" can be deferred to the parent rather than a complex (and inextensible) method signature.Thoughts welcome. Functions on instances seem to be the current trend in trait patterns (in part because the answers of interest may not be available from type information alone - in this context take
a::Transpose{Float64, AbstractMatrix}
(note the lack of a<:
), where we can't know if the parent array type is strided or not until we queryparent(a)
). I'm not sure how I feel aboutnothing
as a sentinel value here, or the generic overload ofstride
.Fixes #29705. Closes #29135 and closes #30429. Touches on JuliaLang/LinearAlgebra.jl#186, #10064, #10889, maybe more. CC @mbauman @timholy @raghav9-97