So, if I understand correctly, the problem is that you need to use the same data to both be a StructArray{T}
and a Matrix{Float64}
. You are correct that the method
julia> struct S
x::Float64
y::Float64
end
julia> StructArray(S(rand(),rand()) for i in 1:10000);
will guarantee that each column is stored contiguously, but not that they are next to each other (they actually can’t be in general, because you can push!
to each column).
What you could do is the following
julia> struct S
x::Float64
y::Float64
end
julia> data = rand(100, 2); # data with SoA layout
julia> s = StructArray{S}(data, dims=2) # this is just a view and does not allocate memory
100-element StructArray(view(::Matrix{Float64}, :, 1), view(::Matrix{Float64}, :, 2)) with eltype S:
S(0.6656012326162104, 0.3785828010062877)
S(0.7640633036875235, 0.7384631357534945)
⋮
S(0.5863124494004175, 0.927251229499223)
S(0.22170197402130576, 0.8404744601671492)
This is similar to your first attempt, but you need to pass the matrix with the correct memory layout (each row is a struct) to be turned effectively into a StructArray
. Otherwise, in your first example, each vector of the StructArray
was a non-contiguous view (a row
of the original matrix).