Matlab: свободная память теряется после вызова функции

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

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

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

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

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

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

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

Ответ 1

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

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

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

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

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

function fragmem(nbytes, chunksize)
%FRAGMEM Fragment the Matlab session 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)

>>