StructArrays Memory Layout

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).

5 Likes