Очень медленная манипуляция с массивом объектов в MATLAB - PullRequest
2 голосов
/ 02 февраля 2012

Я пытаюсь реализовать программу из 8 головоломок с использованием эвристики Манхэттена с использованием ООП в Matlab, где каждый узел представлен объектом «состояние».Тем не менее, я потерял из-за проблем со скоростью реализации массива объектов для очереди.После большого количества проб и ошибок это самое быстрое, что я мог сделать (я ненавижу использовать глобальные объекты, но кажется, что любые попытки передать массив или использовать объект для него сильно замедляют его):

.classdef state < handle    
.    properties
.        position; %3x3 array
.        moves;  
.        blank;
.        parent;
.        prevmove;
.        mdist;
.   end

....


очередь предварительно выделена

queue = repmat(state,1,5000);


.function newfront = q(item,front)

.global queue;
.if isempty(front)
.    newfront = 1;
.    queue(1) = item;
.else
.    for i = front:-1:0
.        if i == 0
.            break;
.        end
.        a = item.mdist;        
.        b = queue(i).mdist;
.        if (a < b)
.            break;
.        else
.            queue(i+1) = queue(i);
.        end    
.    end
.    newfront = front + 1;
.    queue(i+1) = item;
.end
.end

Использование профилировщика MATLAB:

eightpuzzle                     1       67.941 s    2.550 s 
eightpuzzle>q                   4722    59.657 s    59.657 s    
....
118 queue(i+1) = queue(i);     2583916  29.064 s    48.7%   
120 end                        2583916  16.202 s    27.2%   
114 b = queue(i).mdist;        2587318  4.357 s     7.3%    
113 a = item.mdist;            2587318  2.783 s     4.7%    
115 if (a < b)                 2587318  2.721 s     4.6%

есть ли способ заставить его работать быстрее?Интересно отметить, что при использовании

a = item.mdist;        
b = queue(i).mdist;
if (a < b)
...

вместо

if (item.mdist < queue(i).mdist)

общее время выполнения уже сократилось вдвое.

Спасибо!

Ответы [ 2 ]

1 голос
/ 02 февраля 2012

При использовании объектных массивов в MATLAB возникает много дополнительной памяти, как и в структурных массивах. Каждое поле каждого элемента массива имеет свой собственный mxArray, что добавляет значительную нагрузку на память. Рассмотрите возможность использования структуры 1x1 с нескалярными полями, а не структуры 1xN со скалярными полями - она ​​будет значительно меньше в памяти, и доступ к каждому полю будет намного быстрее.

Пример:

Структурный массив 1x100 с двумя скалярными полями "a" и "b" требует (100 * 2) + 1 mxArray объектов в памяти.

Структурному массиву 1x1 с двумя нескалярными полями "a" и "b" размером 1x100 каждое требуется 3 объекта mxArray в памяти.

Ваш массив объектов очень похож на структурный массив, где поля каждого элемента массива можно рассматривать как указатели. Допустим, у вас есть массив объектов «obj» размером 1xN с полями «a» и «b». Ссылка на K-ное поле объекта "a":

OBJ (К) .a

Это операция индекса, а также разыменование указателя mxArray в поле «a».

Я допускаю, что использование скалярного объекта сделает ваш код менее интуитивным, но это компромисс, который вам придется взвесить.

1 голос
/ 02 февраля 2012

Я не знаю, может ли это быть связано с этой темой об общей медлительности ООП в MATLAB: MATLAB OOP работает медленно или я что-то не так делаю?

А вот еще одна ссылка о медленном поведении классов дескрипторов, но, вероятно, она исправлена ​​до тех пор, как об ошибке было сообщено много лет назад: http://www.mathworks.com/matlabcentral/newsreader/view_thread/288746

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...