2015-07-27 1 views
1

У меня есть код, в котором у меня есть определенный класс объектов, каждый из которых имеет несколько полей. С объектно-ориентированной точки зрения это примерно так же классически, как вы можете получить.Матовый массив структур MATLAB очень медленный по сравнению с отдельными массивами ячеек для каждого поля

Я инициализируется код, как:

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 

Я имел предыдущий кодированный это как:

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 

Я затем перейти манипулировать значения, связанные с каждым из полей в каждом объекте различными способами , Второй подход выполнялся примерно в 4 раза быстрее, чем первый. Неэффективность определенно обусловлена ​​этой двойственностью. Единственный код, который я изменил, заключался в переходе от нескольких массивов ячеек к ячейке массива структур. Я знаю, что массивы структур имеют репутацию медленного, но я также вижу структуры, рекомендуемые для перехода к функциям. Что мне здесь не хватает?

Мне очень нравится кодирование аккуратности массива ячеек структур (особенно если вы хотите взять подмножество вроде subset = object(1:4)), но я, очевидно, не хочу принимать вычислительный удар. Какой здесь правильный выбор?

Еще лучше, есть ли скрытый, лучший третий вариант?

+0

В первом примере вам даже не нужно использовать ячейки. Вы динамически обновляете поля * и * размер массива ячеек 'object'. Попробуйте инициализировать 'object' так:' object = struct ('field1', cell (N, 1), 'field2', cell (N, 1), 'field3', cell (N, 1), 'field4', ячейка (N, 1)) 'и затем заполнение значений. Помимо этого вам, вероятно, нужно будет добавить больше кода/информации, чтобы вывести что-то из-за замедления. – Justin

+0

@jucestain: Мне нужны ячейки. Думаю, я пропустил это, когда обобщал свой код, но сейчас я его редактировал. Каждый объект содержит изображения разных размеров и т. Д. Таким образом, хотя у этого может быть матрица 1100x1200, следующая может иметь 980x740 и так далее. Кроме того, я предварительно выделил массив объектов, но вы правы - поля не предварительно распределены. Я думал, что после первой итерации все поля будут выделены. – marcman

+0

В первом примере вам не нужны ячейки. Используя то, что я предложил, вы можете сделать 'object (1) .field1 = ones (10,1)' и 'object (2) .field1 = ones (10,10)', что хорошо.В вашем втором примере вам нужны только ячейки. – Justin

ответ

2

Вы были сбиты с пути, потому что в вашем первоначальном подходе вам понадобилось клеточных массивов для размещения массивов разных размеров в каждом field* индексе.

Однако, когда вы решили использовать структуры в своем втором подходе (лучший подход), вы фактически не использовали , чтобы использовать ячейки массивов. Итак, если вы исследуете этот сегмент кода:

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 

Что на самом деле здесь происходит в каждой итерации, она динамически формируя структуру на каждой итерации. Не только это, но каждый раз, когда вы добавляете новое поле, оно также динамически добавляет новое поле в эту структуру. Это необходимо, только если вы размещаете разные структур в каждом индексе массива ячеек.

Однако, поскольку вы используете одну и ту же структуру в каждом индексе, вы можете просто использовать массив структур. Вы можете предварительно выделить всю вещь с помощью:

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

, а затем перебрать object и заполнить каждое поле, как это необходимо.