Как избежать использования Matlab экспоненциального времени при создании массива объекта дескриптора в качестве свойства объекта - PullRequest
9 голосов
/ 11 октября 2011

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

Мой вопрос: почему это происходит и как этого можно избежать? Правильно ли реализовано предварительное распределение свойств объекта в моем коде или есть фундаментальная проблема с тем, как Matlab обрабатывает эти вещи?

Я написал простой тест для иллюстрации проблемы:

Код простого объекта:

classdef SomeSimpleObject < handle
% SomeSimpleObject defines an Object that has one property

properties
    property=0;
end

methods
    function SimpleObj=SomeSimpleObject()
        if nargin~=0
            SimpleObj.property=1;
        end
    end
end

end

Использование следующего сценария для создания массива этих простых объектов размером 1х10 000 занимает согласно профилировщику 0,4 секунды на моем компьютере:

for n=10000:-1:1 % counting backwards for Memory pre-allocation
    ObjectList(n)=SomeSimpleObject();
end

Однако выполнение одного и того же в конструкторе класса и сохранение массива из 10.000 объектов в качестве свойства занимает 59 секунд, и это быстро ухудшается. Попробуйте создать объект из этого класса (например, a = HostingObject )

classdef HostingObject < handle
% This Objects Hosts a List of Objects that are created in the
% constructor

properties
    ObjectList=SomeSimpleObject
end

methods
    function obj=HostingObject()    
        for n=10000:-1:1 % counting backwards for Memory pre-allocation
            obj.ObjectList(n)=SomeSimpleObject();
        end
    end
end

end

Поиск ответа Я натолкнулся на обсуждение выделения памяти Matlab и сборка мусора . Ответ Михаила (также не связанный напрямую с моим вопросом) заставил меня подумать, что это может быть фундаментальная проблема с тем, как Matlab реализует объекты, но я все еще не уверен.

Ответы [ 3 ]

4 голосов
/ 12 октября 2011

Вдохновленный ответами @ Jonas Heidelberg и @ Tobias Heß Я придумал следующее решение , которое вообще не нуждается в массивах .Объекты хранятся во вспомогательном массиве, и по завершении они копируются в массив свойств:

Код для HostingObject с массивом «post-selection»:

classdef JacobHostingObject < handle
% This Objects Hosts a List of Objects that are created in the constructor

properties
    ObjectList=SomeSimpleObject
end

methods
    function obj=JacobHostingObject()         
        for n=10000:-1:1 % counting backwards for Memory pre-allocation         
            a(n)=SomeSimpleObject(); % auxiliary array for "post-allocation"           
        end            
         obj.ObjectList=a; % "post-allocation"
    end
end

end

Итак, как работают три решения (Джонас, Тобиас и мое)?

Я провел несколько тестов (с MATLAB R2011b 64bit), чтобы сравнить их:

10.000 объектов

Истекшее время: Тобиас: 0,30 сек ;Джейкоб: 0,31 с;Йонас: 2,02 с;Оригинал: 56,79 с

100 000 Объектов

Истекшее время: Тобиас: 2,42 с ;Джейкоб: 2,95 с;Джонас: 203,03 с

1 000 000 Объектов

Истекшее время: Тобиас: 23,84 с ;Джейкоб: 29,18 с

Похоже, версия Tobias - самое быстрое решение

Интересно отметить, что решение Jonas намного лучше, чем оригинал, номасштабируется гораздо хуже двух других решений.Это подтверждает наблюдение, которое я сделал в своем предыдущем вопросе «низкая производительность при хранении объектов-дескрипторов в массиве ячеек» .Немного иронично, что использование техники, которая была причиной моей более ранней проблемы, оказывается улучшением этой проблемы.Тем не менее, решение Tobias даже отвечает и на мой старый вопрос (я опубликую там ссылку).

Однако до сих пор не ясно, что на самом деле происходит внутри MATLAB, что вызывает различия в производительности .Может быть полезно понять это, чтобы не столкнуться с подобными проблемами в будущем!

4 голосов
/ 11 октября 2011

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

>> tic,a=HostingObject;toc
Elapsed time is 105.320128 seconds.

>> tic,a=JonasHostingObject;toc
Elapsed time is 2.394570 seconds.

Объект определен следующим образом:

classdef JonasHostingObject < handle
properties
    ObjectList
end
methods
    function obj=JonasHostingObject()    
        obj.ObjectList=cell(10000,1);
        for n=1:10000
            obj.ObjectList{n}=SomeSimpleObject();
        end
    end
end    
end

Я использую MATLAB R2011a 64bit,в случае, если это имеет значение.

2 голосов
/ 11 октября 2011

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

classdef HostingObject < handle
% This Objects Hosts a List of Objects that are created in the
% constructor

properties
    ObjectList=SomeSimpleObject
end

methods
    function obj=HostingObject()

        % Creating first a cell array
        helpCell = cell(10000,1);
        for n=1:10000 
            helpCell{n}=SomeSimpleObject();
        end

        % Convert the cell array to the object array
        obj.ObjectList = horzcat(helpCell{:});

    end

end

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