MATLAB занимает много времени после последней строки функции - PullRequest
8 голосов
/ 24 ноября 2010

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

ts1 = tic;
disp ('calling function');
functionCall(args);
disp (['control returned to caller - ', num2str(toc(ts1))]); 

Первая строка вызываемой функции - ts2 = tic, а последняя -

disp (['last line of function- ', num2str(toc(ts2))]);

Результат

вызывающая функция

последняя строка функции - 24.0043

элемент управления возвращен вызывающей стороне - 49,857

Поискивая в паутинах, я думаю, это признак того, как MATLAB управляет памятью. Он освобождает от возвратов функций, а иногда это занимает много времени. Функция выделяет несколько больших (~ 1 миллион элементов) массивов. Он также работает с дескрипторами, но не создает никаких новых объектов дескрипторов и не хранит дескрипторы явно. Мои вопросы:

  1. Это определенно проблема управления памятью?
  2. Существует ли какой-либо систематический способ диагностики причин этой функции, в отличие от других, которые быстро возвращаются?
  3. Существуют ли общие советы по сокращению времени, которое MATLAB тратит на очистку при выходе из функции?

Ответы [ 3 ]

4 голосов
/ 24 ноября 2010

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

Вы можете попробовать установить переменные вручную в [] перед выходом из функции - т.е.сборка мусора вручную.Этот метод также помогает против утечек памяти в предыдущих версиях MATLAB.Теперь MATLAB будет тратить время не на end, а на myVar=[];

. Вы можете решить проблему, работая без каких-либо ссылок - анонимных функций, вложенных функций, классов обработки, не используя cellfun и arrayfun.

Если вы достигли «барьера производительности» MATLAB, то, возможно, вам следует просто изменить среду.Я не вижу никакого смысла начинать сегодня новый проект в MATLAB, кроме случаев, когда вы используете SIMULINK.Python отлично подходит для технических вычислений, и с C # вы также можете делать много вещей, которые MATLAB делает, используя бесплатные библиотеки .И оба они настоящие языки программирования и являются бесплатными, в отличие от MATLAB.

2 голосов
/ 02 декабря 2010

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

Функция, для которой потребовалось много времени, была вызвана для базового объекта, который содержал вектор объектов-дескрипторов.Когда я изменил определение базового объекта для расширения дескриптора, я устранил задержку при закрытии функции.

Я считаю, что происходило следующее: когда я передавал базовый объект своей функции, он создавалкопия этого объекта (по умолчанию MATLAB передается по значению).Это не занимает много времени, но когда функция закрывается, она уничтожает копию объекта, в результате чего она просматривает вектор объектов-дескрипторов, чтобы убедиться, что нет никаких сирот, которые нужно было очистить.Я полагаю, что эта операция выполняла MATLAB долгое время.

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

Это подсказывает мне общее правило:

Если функции требуется много времени для очистки своего рабочего пространства при выходе, и вы передаете много данных или сложных структур с помощьюзначение, попробуйте инкапсулировать аргументы этой функции в объекте-дескрипторе

Это позволит избежать дублирования и, следовательно, займет много времени для очистки при выходе.Недостатком является то, что ваша функция теперь может неожиданно изменять ваши входные данные, потому что MATLAB не имеет возможности объявить аргумент const, как в c ++.

0 голосов
/ 27 ноября 2010

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

workArr = zeros(1,1e6); % allocate once
...
functionCall(args,workArr); % call with extra argument
...
functionCall(args,wokrArr); % call again, no realloc of workArr needed
...

Внутри functionCall вы можете позаботиться об инициализации и / или переустановке workArr, например

[workArr(:)] = 0; % reset work array
...