I was originally planning on rewriting LoopVectorization to add some important features and Julia 1.6 support at the same time, but progress on that front has been slow, so I’ve decided to first focus on just switching over the old code to the new VectorizationBase.jl and ArrayInterface.jl, without yet taking advantage of some of the new features if the associated changes are unnecessary.
I hope to make a release this weekend, but it’ll depend on how long it takes me to get the remaining tests to pass.
To get LoopVectorization support, you’ll need to define a few methods.
julia> using ArrayInterface, HybridArrays, StaticArrays
julia> a = HybridMatrix{3,StaticArrays.Dynamic()}(randn(3,100));
julia> ArrayInterface.strides(a)
ERROR: MethodError: no method matching strides(::HybridMatrix{3, StaticArrays.Dynamic(), Float64, 2, Matrix{Float64}})
Closest candidates are:
strides(::SubArray) at subarray.jl:329
strides(::Union{Base.ReinterpretArray{T, N, S, A, IsReshaped} where S where IsReshaped where A<:Union{SubArray{T, N, A, I, true} where I<:Union{Tuple{Vararg{Real, N} where N}, Tuple{AbstractUnitRange, Vararg{Any, N} where N}} where A<:DenseArray where N where T, DenseArray} where N where T, Base.ReshapedArray{T, N, A, MI} where MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64}, N} where N} where A<:Union{Base.ReinterpretArray{T, N, S, A, IsReshaped} where S where IsReshaped where A<:Union{SubArray{T, N, A, I, true} where I<:Union{Tuple{Vararg{Real, N} where N}, Tuple{AbstractUnitRange, Vararg{Any, N} where N}} where A<:DenseArray where N where T, DenseArray} where N where T, SubArray{T, N, A, I, true} where I<:Union{Tuple{Vararg{Real, N} where N}, Tuple{AbstractUnitRange, Vararg{Any, N} where N}} where A<:DenseArray where N where T, DenseArray} where N where T, DenseArray}) at reinterpretarray.jl:160
strides(::Base.ReinterpretArray) at reinterpretarray.jl:156
...
Stacktrace:
[1] strides(A::HybridMatrix{3, StaticArrays.Dynamic(), Float64, 2, Matrix{Float64}})
@ ArrayInterface ~/.julia/dev/ArrayInterface/src/stridelayout.jl:298
[2] top-level scope
@ REPL[3]:1
julia> pointer(a)
ERROR: conversion to pointer not defined for HybridMatrix{3, StaticArrays.Dynamic(), Float64, 2, Matrix{Float64}}
Stacktrace:
[1] error(s::String)
@ Base ./error.jl:33
[2] unsafe_convert(#unused#::Type{Ptr{Float64}}, a::HybridMatrix{3, StaticArrays.Dynamic(), Float64, 2, Matrix{Float64}})
@ Base ./pointer.jl:67
[3] pointer(x::HybridMatrix{3, StaticArrays.Dynamic(), Float64, 2, Matrix{Float64}})
@ Base ./abstractarray.jl:1110
[4] top-level scope
@ REPL[4]:1
julia> ArrayInterface.size(a) # not static
(3, 100)
julia> B = @MMatrix rand(3,4);
julia> ArrayInterface.strides(B)
(ArrayInterface.StaticInt{1}(), ArrayInterface.StaticInt{3}())
julia> pointer(B)
Ptr{Float64} @0x00007f73882a7d50
julia> ArrayInterface.size(B) # static
(ArrayInterface.StaticInt{3}(), ArrayInterface.StaticInt{4}())
julia> ArrayInterface.strides(B) # static
(ArrayInterface.StaticInt{1}(), ArrayInterface.StaticInt{3}())
HybridArrays will need a few methods defined, but StaticArrays.MArrays are good to go for the next release of LoopVectorization:
julia> using VectorizationBase # master branch; needs to be 0.13
julia> stridedpointer(B) # if this function works, the array should work
VectorizationBase.StridedPointer{Float64, 2, 1, 0, (1, 2), Tuple{StaticInt{8}, StaticInt{24}}, Tuple{StaticInt{1}, StaticInt{1}}}(Ptr{Float64} @0x00007f73882a7d50, (StaticInt{8}(), StaticInt{24}()), (StaticInt{1}(), StaticInt{1}()))
The list of methods:
ArrayInterface.size(A::HybridArray) = ...
ArrayInterface.strides(A::HybridArray) = ...
Base.unsafe_convert(::Type{Ptr{T}}, A::HybridArray{S,T}) where {S,T} = pointer(A.data)
ArrayInterface.contiguous_axis(::Type{<:HybridArray}) = ArrayInterface.Contiguous{1}()
ArrayInterface.contiguous_batch_size(::Type{<:HybridArray}) = ArrayInterface.ContiguousBatch{0}()
ArrayInterface.stride_rank(::Type{<:HybridArray{<:Any,<:Any,N}}) where {N} = ArrayInterface.StrideRank{ntuple(identity,Val(N))}()
I didn’t test, but all but the first 2 should be close to something that works.