marcman
marcman

Reputation: 3383

MATLAB cell array of structs very slow compared to individual cell arrays for each field

I have some code where I have a certain class of objects, each of which has a number of fields. From an object oriented perspective, it's about as classic as you can get.

I initialized the code as:

object = cell(N, 1);
% Each field may contain matrices of different dimensions at each iteration
for i = 1 : N
    object{i}.field1 = ones(1000, 3);
    object{i}.field2 = imread('some_image.png');
    object{i}.field3 = (1:.002: 4);
    object{i}.field4 = im > 0;
    ...
    % And so on for more large matrices and such
end

I had previous coded this as:

field1 = cell(N, 1);
field2 = cell(N, 1);
field3 = cell(N, 1);
field4 = cell(N, 1);
....
for i = 1 : N
    field1{i} = ones(1000, 3);
    field2{i} = imread('some_image.png');
    field3{i} = (1:.002: 4);
    field4{i} = im > 0;
    ...
    % And so on for more large matrices and such
end

I then proceed to manipulate the values associated with each of the fields in each object in various ways. The second approach ran about 4 times faster than the first. The inefficiency is definitely due to this duality. The only code I changed was switching from multiple cell arrays to cell a array of structs. I know arrays of structs have a reputation for being slower, but I also see structs recommended for passing into functions. What am I missing here?

I really like the coding neatness of the cell array of structures (particularly when you want to take a subset like subset = object(1:4)), but I obviously don't want to take the computational hit. What's the right choice here?

Better yet, is there a hidden, better third option?

Upvotes: 1

Views: 1090

Answers (1)

JustinBlaber
JustinBlaber

Reputation: 4650

You were led astray because in your initial approach, you needed cell arrays in order to house different sized arrays in each field* index.

However, when you decided to use structures in your second approach (the better approach), you didn't actually need to use cell arrays. So, if you examine this code segment:

for i = 1 : N
    object{i}.field1 = ones(1000, 3);
    object{i}.field2 = imread('some_image.png');
    object{i}.field3 = (1:.002: 4);
    object{i}.field4 = im > 0;
    ...
    % And so on for more large matrices and such
end

What's actually happening here is in each iteration, it is dynamically forming a structure on each iteration. Not only that, but every time you add a new field it is also dynamically adding a new field to that structure. This is only necessary if you are housing different structures in each index of the cell array.

However, since you are using the same structure in each index, you can simply use an array of structures. You can preallocate the entire thing by using:

object = struct('field1', cell(N,1), 'field2', cell(N,1), ...);

and then iterate over object and fill out each field as needed.

Upvotes: 2

Related Questions