Reputation: 2240
Is there value in attempting to pre-allocate an array of structs when the size of the fields is variable? For example:
A.x = randn(1,randi(100));
A.y = randn(1,randi(100));
for k = 2:1000
A(k).x = randn(1,randi(100));
A(k).y = randn(1,randi(100));
end
I could create the first entry and then use repmat, but MATLAB would still have to deal with the unknown field lengths. In my tests there is little/no improvement compared to just letting it grow dynamically. Incidentally, growing it with brackets (e.g. A = [A nextEntry]) is much slower.
Is there a clever way to do a pre-alloc to speed this up?
Upvotes: 2
Views: 692
Reputation: 65430
The way that MATLAB stores struct
arrays is that the meta-data about the struct (the dimensions, the fieldnames, etc.) is stored in one place in memory and the contents (values) of each field are stored separately and pointers to their location are inserted into the meta-data so that they can be located when requested.
For this reason, if you want to initialize a struct
you can initialize it with all the contents set to []
. You only need to ensure that the number of fields and the dimensions of the initial struct
are the correct size so that we have enough space to store all of the pointers to the data that it will eventually contain.
Then you can fill in the fields as-needed, their value will be assigned to fresh memory, and their pointer will be stored in the meta-data in the pre-allocated location.
A relevant article from Loren's blog
So in your case you can simply pre-allocate your struct
with:
A = struct('x', cell(1, 1000), 'y', cell(1, 1000));
And fill it with:
for k = 1:numel(A)
A(k).x = randn(1, randi(100));
A(k).y = randn(1, randi(100));
end
As far as why growing A
using [A newA]
is slower. This causes us to have to "grow" the meta-data component of the struct
each time through the loop, which actually requires an entire copy of the meta-data to be made to perform the expansion each time.
Upvotes: 1