Функция Matlab Get Property, вызывающая проблемы с производительностью - PullRequest
3 голосов
/ 02 августа 2011

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

    function value =  get.error(obj)
        value = obj.error;
    end

Теперь, видятак как этот код полностью избыточен, я решил полностью удалить функцию get, но это приводит к невероятному замедлению в одном разделе моего кода, где свойство 'error' вызывается неоднократно.

В этом разделе кода профилировщик не явно говорит , что отсутствующая функция get является причиной проблемы (он говорит, что все время тратится впустую в конце «a» для'loop), но когда я снова добавляю функционально бесполезный код, проблема с производительностью исчезает.

Почему удаление этой бесполезной функции get замедляет мой код?

РЕДАКТИРОВАТЬ: Я имеюдостаточно изолировал проблему, чтобы опубликовать некоторые примеры кода.

Вот фиктивная версия вызова метода, которая имеет проблему: enter image description here

Вот профиль кода безбесполезный геттер: enter image description here

и с магическим бесполезным геттером: enter image description here

Обратите внимание, что требования к производительности выглядят следующим образом:

  1. использовать некоторое свойство моего объекта 'pool' в вычислении, установленном для любой переменной.Свойство 'error' привлекло мое внимание, но ошибка возникает со всеми свойствами в одной и той же ситуации.

  2. вычисление включает в себя все, даже '. * 0' вызывает этоЗамедление, но один установленный термин не замедляется (например, obj.pools (i) .delta = obj.pools (i) .error)

EDIT 2:

Вот полный класс пула;возможно, это поможет:

classdef pool < handle

properties
    name;
    unit_count;
    activation;
    net_input = 0;
    %all projections now incoming
    projections = [];
    error; % same is dEd net for rbp
    target;
    clamped_error = false;
    delta;
    clamped_activation = 0; %0 no clamp, 1 soft clamp, 2 hard clamp
    copyback = false;
    copy_from;
    type = 'hidden';

    activation_history;
    error_history;

end

methods
    function obj = pool(name,count,type,copy_from)
        obj.name = name;
        assignin('caller', name, obj);
        obj.unit_count = count;
        obj.error = zeros(1,count);
        obj.target = zeros(1,count);
        obj.delta = zeros(1,count);
        obj.activation = zeros(1,count);
        obj.net_input = zeros(1,count);
        obj.activation_history(:,1) = zeros(1,count);
        obj.error_history(:,1) = zeros(1,count);
        if nargin > 2
            obj.type = type;
            if nargin == 4
                obj.clamped_activation = 2;
                obj.activation = ones(1,count)/2;
                obj.copy_from = copy_from;
                obj.copyback = true;
            end
        else
            obj.type = 'hidden';
        end
        switch obj.type
            case 'input'
                obj.clamped_activation = 2;
            case 'output'
                obj.clamped_error = true;
            case 'bias'
                obj.clamped_activation = 2;
                obj.activation = 1;
            case 'hidden'
        end

    end

    function proj = connect(obj,send_pool,proj_var)
        %see if you need a new projection or if the user provided one

        if nargin == 2
            proj = projection(obj, send_pool);
        else
            proj = proj_var;
        end
        obj.projections = [obj.projections struct('from',send_pool,'using',proj)];
    end


    function value =  get.error(obj)
        value = obj.error;
    end

end

end

1 Ответ

1 голос
/ 03 августа 2011

Звучит как Matlab JIT или странность интерпретатора.

Возможно, вы наблюдаете ошибку Matlab, связанную с управлением памятью MCOS, как это обсуждалось в Индексирование массива данных очень медленно с Statistics Toolbox . Эта ошибка выглядит так, как будто она вызывает ложное глубокое копирование объектов при обращении к их полям в некоторых случаях. Если в ваших объектах пула есть массивы ячеек или другие сложные структуры, это может вызвать похожее поведение - они копируются в новые переменные, и, возможно, стоимость освобождения указывается на «конце».

Мне удалось воспроизвести похожие удивительные медленные результаты в нескольких версиях Matlab. Но я не смог показать никаких отличий от присутствия добытчика.

Файл fooclass.m.

classdef fooclass
    properties
        error = 42;
        whatever = 42;
        delta = 1;
        bigjunk = num2cell(rand(1000,40));
        %bigjunk = rand(1000,10000);  % non-cell does not cause slowdown
    end

    methods        
%         function out = get.error(obj)
%             out = obj.error;
%         end
    end

end

Файл looper.m.

classdef looper
    properties
        pools
    end

    methods
        function obj = looper()
            obj.pools = repmat(fooclass(), [1 5]);;
        end

        function weird(obj)
        p = obj.pools;
        n = numel(p);
        for i = 1:n
            dummy = obj.pools(i).error .* 0;
        end
        end
    end
end

Воспроизвести:

>> lp = looper;
>> tic; for i = 1:100; weird(lp); end; toc
Elapsed time is 0.600428 seconds.

Это на моем R2011a (предварительный выпуск) на 64-битной Windows 7. Это медленно. Время пропорционально размеру bigjunk, и профилировщик говорит, что почти все происходит в строке p = obj.pools. Это говорит о том, что ссылка на объект вызывает копию, а не использует оптимизацию копирования при записи, как это должно быть. Или это обход объекта графа, или что-то. Нечто подобное может происходить с вашим кодом.

Лучше всего просто объяснить это странностью интерпретатора, оставить получатель там, если он ускоряет ваш код, и дождаться исправления в следующем выпуске. Звуки, которые стоит отправить в MathWorks в виде сообщения об ошибке.

...