Matlab: свободная память теряется после вызова функции - PullRequest
10 голосов
/ 21 июля 2010

У меня проблемы с управлением памятью в Matlab.Наконец, это приводит к нехватке свободной памяти и ошибке. Я попытался определить проблему и нашел одну интересную «особенность»: почему-то я теряю свободную память в Matlab.

Я делаю следующее:
1) Запускаю Matlab
2) набираю «память», получаю: Максимально возможный массив: 1293 МБ, Память доступна для всех массивов: 1456 МБ
3)Я назову функцию.Функция довольно длинная, поэтому ее сложно вставить сюда.Но в основном это загружает 5 ок.300 МБ MAT файлов (последовательно), выбирает несколько значений и возвращает их.Возвращенная матрица ок.1,2mb (4650x35 double)
4) Я очищаю все переменные в рабочей области («очистить все»)
5), набрав «memory», получаю: Максимально возможный массив: 759 МБ, Память, доступная для всех массивов: 1029mb

Если я повторю шаги с 3) по 5), номера памяти будут постоянными.

Так что же здесь не так?Где я теряю 400 Мб свободного места?Память, используемая Matlab, постоянна и составляет около 330 Мб.

У кого-нибудь есть идеи, что здесь не так?Или это что-то совершенно естественное, но я скучаю по нему?

Спасибо
Томас

PS: Я использую Matlab 2010a и Win 7 pro 32bit.

1 Ответ

16 голосов
/ 21 июля 2010

Хорошая часть этой "потерянной" памяти, вероятно, связана с фрагментацией памяти. Когда Matlab выделяет и освобождает массивы в течение сеанса, память разбивается на более мелкие области, а часть теряется из-за накладных расходов в диспетчере памяти как на уровне Matlab, так и на нижележащих уровнях C. Служебная нагрузка не считается Matlab как «используемая», поскольку она не используется для хранения значений массива M-кода. Некоторая память может также потребляться Matlab, загружая дополнительные M-файлы и библиотеки, выделяя внутренние буферы или структуры, или расширением кучи Java во встроенной JVM Matlab. Это нормально. После некоторой работы у Matlab будет не так много памяти, как в новой сессии.

AFAIK, когда происходит низкоуровневая фрагментация, вы ничего не можете сделать, чтобы устранить ее, кроме перезапуска Matlab. Выделение большого количества маленьких массивов может ускорить фрагментацию. Это иногда случается, если вы используете большие ячейки или большие массивы объектов. Поэтому, если у вас возникли проблемы, вам может понадобиться уменьшить пиковое использование памяти в функции, разбив работу на меньшие куски, уменьшив использование ячеек и так далее. И если у вас есть большие массивы cellstr в файлах MAT, преобразуйте их в char. «Верхний предел» распределения - это то, что управляет фрагментацией, поэтому, если вы можете разбить свой набор данных на более мелкие порции, вы можете разместить его в меньшем объеме памяти.

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

Чтобы помочь отладке, выполните "dbstop if all error", которая будет вызвана OOM. Оттуда вы можете использовать whos и отладчик, чтобы узнать, где занято место, когда вы исчерпываете память. Это может выявить временные переменные, которые необходимо очистить, или предложить способы разбиения работы.

Если вы хотите поэкспериментировать, чтобы увидеть, как выглядит фрагментация и как она влияет на вывод memory (), вот функция, которая просто создаст некоторую фрагментацию.

function fragmem(nbytes, chunksize)
%FRAGMEM Fragment the Matlab session's memory
if nargin < 2; chunksize = 1*2^10; end

nbytes = nbytes - rem(nbytes, chunksize);

nsteps = 100; % to make initial input relatively small
c = cell([1 nsteps]);
stepsize = nbytes / nsteps;
chunksperstep = ceil(stepsize / chunksize);
fprintf('Fragmenting %d MB memory into %d KB chunks (%d steps of %d chunks)\n',...
    round(nbytes/2^20), round(chunksize/2^10), nsteps, chunksperstep);

x = zeros([1 chunksperstep * chunksize], 'uint8');
colsizes = repmat(chunksize, [1 chunksperstep]);
for i = 1:nsteps
    c{i} = mat2cell(x, 1, colsizes);
end

Фрагментация 300 МБ порциями по 1 КБ на моей машине приводит к «потере» на моей машине win32 размера, который вы видите.

>> memory
Maximum possible array:            1384 MB (1.451e+009 bytes) *
Memory available for all arrays:   1552 MB (1.627e+009 bytes) **
Memory used by MATLAB:              235 MB (2.463e+008 bytes)
Physical Memory (RAM):             3311 MB (3.472e+009 bytes)

>> fragmem(300*2^20)
Fragmenting 300 MB memory into 1 KB chunks (100 steps of 3072 chunks)
>> memory
Maximum possible array:            1009 MB (1.059e+009 bytes) *
Memory available for all arrays:   1175 MB (1.232e+009 bytes) **
Memory used by MATLAB:              257 MB (2.691e+008 bytes)
Physical Memory (RAM):             3311 MB (3.472e+009 bytes)

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