How to initialize two dimensional array of arrays?

Dear community,

I fail to initialize an array of type Array{Array{UInt16,1},2}. In particular I tried it via a mutable struct, which in my case then leads to type Array{Array{UInt16,N} where N,2} which I can use as wanted. However, it seems to me that there is a conversion hidden behind that, since accessing elements allocates memory. Here is a small example:

using BenchmarkTools

mutable struct myinst
    R::Array{Array{UInt16},2}
end

function main()
    N = 1000
    W = 500
    K = 1000

    inst = myinst( Array{Array{UInt16}}(undef,0,0) )
    inst.R  = [Array{UInt16}[] for i=1:N, j=1:W]

    S = Array{Array{UInt16}}(undef,0,0)
    S = [Array{UInt16}[] for i=1:N, j=1:W]

    println( "typeof inst.R: ", typeof(inst.R) )
    println( "typeof S: ", typeof(S) )
    return nothing
end
main()

which outputs:

typeof inst.R: Array{Array{UInt16,N} where N,2}
typeof S: Array{Array{Array{UInt16,N} where N,1},2}

I then fill inst.R[i,j] with arrays of different sizes. However, reading the data afterwards allocates memory. Can you please tell me how to initialize such a structure correctly? Is the memory allocation when reading the data really due to some conversion in the background?
Thank you in advance, Michael.

Your field type is Array{Array{UInt16}, 2}, which isn’t quite right. That type signature means “a two-dimensional array, where each element is (an array of UInt16 of any dimension)”.

What is the dimensionality of each element of R? If R is a 2D array of 1D arrays of UInt16, then you want:

Array{Array{UInt16, 1}, 2}

or, equivalently:

Matrix{Vector{UInt16}}

Or if each element of R is a 2D array of UInt16, then you want:

Array{Array{UInt16, 2}, 2}

which is exactly the same as Matrix{Matrix{UInt16}}.

2 Likes

You should really use the Vector and Matrix aliases. It is extremely easy to make a mistake otherwise.

It also makes your code much more readable.

1 Like

Wow, that easy. Thank you @rdeits it works, thank you @DNF I will consider that.

However, what I still do not understand. Even if the inner array is of any dimension as I initially defined it, is this the reason that reading data from it allocates memory? At least I cannot imagine why this should be the case.

This is typical when you’re working with data that is of an abstract type, the compiler is unable to specialize the code. It’s fine to use abstract types for dispatch, but your data should preferably have a concrete type.

3 Likes

Okay, this makes sense to me. Thank you so much!