Источник многих "из памяти" проблемы часто включает анализ или обработку существующего большого набора данных такой как в файле или базе данных. Это требует обеспечения всех или части набора данных в процесс MATLAB. Следующие методы имеют дело с минимизацией необходимой памяти во время этого этапа.
Только импортируйте в MATLAB такое количество большого набора данных, как вам нужно для проблемы, которую вы пытаетесь решить. Это обычно не проблема при импорте из источников, таких как база данных, где можно явным образом искать элементы, совпадающие с запросом. Но это - типичная проблема с загрузкой большого плоского текста или двоичных файлов. Вместо того, чтобы загружать целый файл, используйте соответствующую функцию MATLAB, чтобы загрузить части файлов.
FileType | Частичная загрузка |
---|---|
Matfile | Загрузите часть переменной путем индексации в объект, который вы создаете с функцией |
Текст | Используйте функцию |
Двоичный файл | Можно использовать низкоуровневые функции ввода-вывода двоичного файла, такие как |
Отобразите, HDF, аудио и видео | Многие функции MATLAB, которые поддерживают загрузку от этих типов файлов, позволяют вам выбирать фрагменты данных, чтобы читать. Для получения дополнительной информации смотрите страницы ссылки на функцию, перечисленные в Поддерживаемых Форматах файлов для Импорта и Экспорта. |
Рассмотрите обработку блока, то есть, обработав большой набор данных один раздел за один раз в цикле. Сокращение размера самого большого массива в наборе данных уменьшает размер любых копий или необходимых временных файлов. Можно использовать этот метод любым из двух способов:
Для подмножества приложений, что можно ворваться в отдельные фрагменты и процесс независимо.
Для приложений, которые только полагаются на состояние предыдущего блока, такого как фильтрация.
Старайтесь не создавать большие временные переменные, и также сделайте его практикой, чтобы очистить те временные переменные, которые вы используете, когда они больше не необходимы. Например, когда вы создаете большой массив нулей, вместо того, чтобы сохранить во временную переменную A
, и затем преобразовать A
в сингл:
A = zeros(1e6,1); As = single(A);
используйте только одну команду, чтобы сделать обе операции:
A = zeros(1e6,1,'single');
Используя функцию repmat
, предварительное выделение массивов и циклы for
являются другими способами работать над данными nondouble
, не требуя временного хранения в памяти.
При работе с большими наборами данных, иметь в виду, что MATLAB делает временную копию входной переменной, если вызванная функция изменяет свое значение. Это временно удваивает память, требуемую сохранить массив, который заставляет MATLAB генерировать ошибку, если достаточная память не доступна.
Один способ использовать меньше памяти в этой ситуации состоит в том, чтобы использовать вложенные функции. Вложенная функция совместно использует рабочую область всех внешних функций, предоставляя доступ к вложенной функции к данным за пределами его обычного осциллографа. В примере, показанном здесь, вложенная функция, setrowval
имеет прямой доступ к рабочей области внешнего функционального myfun
, делая ненужным передать копию переменной в вызове функции. Когда setrowval
изменяет значение A
, это изменяет его в рабочей области функции вызова. Нет никакой потребности использовать дополнительную память, чтобы содержать отдельный массив для функции, вызванной, и также нет никакой потребности возвратить измененное значение A
:
function myfun A = magic(500); function setrowval(row, value) A(row,:) = value; end setrowval(400, 0); disp('The new value of A(399:401,1:10) is') A(399:401,1:10) end
MATLAB предоставляет вам различные размеры классов данных, такие как double
и uint8
, таким образом, вы не должны использовать большие классы, чтобы сохранить ваши меньшие сегменты данных. Например, 7 Кбайтам требуется меньше памяти, чтобы сохранить 1 000 маленьких значений беззнаковых целых чисел с помощью класса uint8
, чем это делает с double
.
Числовой класс, который необходимо использовать в MATLAB, зависит от намеченных действий. Класс по умолчанию double
дает лучшую точность, но требует 8 байтов за элемент памяти хранилищу. Если вы намереваетесь выполнить сложную математику, такую как линейная алгебра, необходимо использовать класс с плавающей точкой, такой как double
или single
. Класс single
требует только 4 байтов. Существуют некоторые ограничения на то, что можно сделать с классом single
, но большинство Математических операций MATLAB поддерживается.
Если только необходимо выполнить простую арифметику, и вы представляете исходные данные как целые числа, можно использовать целочисленные классы в MATLAB. Следующее является списком числовых классов, требования к памяти (в байтах), и поддерживаемые операции.
Класс (тип данных) | Байты | Поддерживаемые операции |
---|---|---|
single | 4 | Большая часть математики |
double | 8 | Вся математика |
logical | 1 | Логические/условные операции |
int8, uint8 | 1 | Арифметика и некоторые простые функции |
int16, uint16 | 2 | Арифметика и некоторые простые функции |
int32, uint32 | 4 | Арифметика и некоторые простые функции |
int64, int64 | 8 | Арифметика и некоторые простые функции |
Массивы MATLAB (реализованный внутренне как mxArrays
) требуют, чтобы комната сохранила метаинформацию о данных в памяти, такой как тип, размерности и атрибуты. Это берет приблизительно 80 байтов за массив. Эти издержки только становятся проблемой, когда у вас есть большое количество (например, сотни или тысячи) маленького mxArrays
(например, скаляры). Списки команд whos
память, используемая переменными, но, не включают эти издержки.
Поскольку простые числовые массивы (включение того mxArray
) имеют наименее служебное, необходимо использовать их по мере возможности. Когда данные являются слишком комплексными, чтобы сохранить в простом массиве (или матрица), можно использовать другие структуры данных.
Массивы ячеек состоят из отдельного mxArrays
для каждого элемента. В результате массивы ячеек со многими маленькими элементами имеют большие издержки.
Структуры требуют подобной суммы издержек на поле (см. Заголовки Массивов). Структуры со многими полями и маленьким содержимым имеют большие издержки и должны избежаться. Большой массив структур с полями числового скаляра требует намного большей памяти, чем структура с полями, содержащими большие числовые массивы.
Также обратите внимание на это, в то время как MATLAB хранит числовые массивы в непрерывной памяти, дело обстоит не так для структур и массивов ячеек.
При чтении данных из двоичного файла с fread
это - распространенная ошибка, чтобы задать только класс данных в файле, а не класс данных использование MATLAB, если это находится в рабочей области. В результате double
по умолчанию используется, даже если вы читаете только 8-битные значения. Например,
fid = fopen('large_file_of_uint8s.bin', 'r'); a = fread(fid, 1e3, 'uint8'); % Requires 8k whos a Name Size Bytes Class Attributes a 1000x1 8000 double a = fread(fid, 1e3, 'uint8=>uint8'); % Requires 1k whos a Name Size Bytes Class Attributes a 1000x1 1000 uint8
Если ваши данные содержат много нулей, рассмотрите использование разреженных массивов, которые хранят только ненулевые элементы. Следующий пример сравнивает пробел, требуемый для устройства хранения данных массива в основном нулей:
A = eye(1000); % Full matrix with ones on the diagonal As = sparse(A); % Sparse matrix with only nonzero elements whos Name Size Bytes Class Attributes A 1000x1000 8000000 double As 1000x1000 24008 double sparse
Вы видите, что этот массив требует, чтобы только приблизительно 4 Кбайта хранились столь же разреженные, но приблизительно 8 Мбайт как полная матрица. В целом, для разреженного двойного массива с nnz
ненулевые элементы и столбцы ncol
, требуемая память
16 * nnz
+ 8 * ncol
+ 8 байтов (на 64-битной машине)
12 * nnz
+ 4 * ncol
+ 4 байта (на 32-битной машине)
Обратите внимание на то, что MATLAB не поддерживает все математические операции на разреженных массивах.
MATLAB всегда использует непрерывный сегмент памяти, чтобы сохранить числовой массив. Когда вы управляете этими данными, однако, непрерывный блок может стать фрагментированным. Когда память фрагментируется, может быть много свободного пространства, но недостаточно непрерывной памяти, чтобы сохранить новую большую переменную. Увеличение фрагментации может использовать значительно больше памяти, чем необходимо.
В ходе сеанса работы с MATLAB память может стать фрагментированной из-за динамического выделения памяти и освобождения. for
и циклы while
, которые инкрементно увеличиваются или растут, размер структуры данных каждый раз через цикл, могут добавить к этой фрагментации, когда они должны неоднократно находить и выделять большие блоки памяти, чтобы хранить данные.
Чтобы сделать более эффективное использование из вашей памяти, предварительно выделите блок памяти, достаточно большой, чтобы содержать матрицу в ее итоговом размере прежде, чем ввести цикл. Когда вы предварительно выделяете память для массива, MATLAB резервирует достаточный непрерывный пробел для целого полноразмерного массива в начале вычисления. Если у вас есть этот пробел, можно добавить элементы в массив, не имея необходимость постоянно выделять новое место для него в памяти.
Для получения дополнительной информации о предварительном выделении смотрите Предварительное выделение.
MATLAB использует метод кучи управления памятью. Это запрашивает память от операционной системы, когда существует недостаточно памяти, доступной в куче, чтобы сохранить текущие переменные. Это снова использует память, пока размер требуемого сегмента memory доступен в куче.
Следующие операторы могут потребовать приблизительно 4,3 Мбайт RAM. Это вызвано тем, что MATLAB не может смочь снова использовать место, ранее занятое двумя массивами на 1 Мбайт при выделении места для массива на 2,3 Мбайта:
a = rand(1e6,1); b = rand(1e6,1); clear c = rand(2.3e6,1);
Самый простой способ предотвратить сверхвыделение памяти состоит в том, чтобы выделить самые большие векторы сначала. Эти операторы требуют только приблизительно 2,0 Мбайт RAM:
c = rand(2.3e6,1); clear a = rand(1e6,1); b = rand(1e6,1);
На 32-битном Microsoft® Windows® рабочая область MATLAB может фрагментировать в зависимости от времени вследствие того, что диспетчер памяти Windows не возвращает блоки определенных типов и размеров к операционной системе. Очистка рабочего пространства MATLAB не решает эту проблему. Можно минимизировать проблему путем выделения самых больших переменных сначала. Это не может обратиться, однако, к возможной фрагментации рабочей области, которая происходит от непрерывного использования MATLAB за многие дни и недели, например. Единственное решение этого состоит в том, чтобы сохранить вашу работу и перезапустить MATLAB.
Команда pack
, которая сохраняет все переменные на диск и загружает их назад, не помогает с этой ситуацией.
Один простой способ увеличить объем памяти, который вы имеете в наличии, состоит в том, чтобы очистить большие массивы, которые вы больше не используете.
Если ваша программа генерирует очень большие объемы данных, рассмотрите запись данных к диску периодически. После сохранения того фрагмента данных используйте функцию clear
, чтобы удалить переменную из памяти и продолжить генерацию данных.
Когда вы работаете с очень большим набором данных неоднократно или в интерактивном режиме, очищаете старую переменную сначала, чтобы сделать пробел для новой переменной. В противном случае MATLAB требует временного хранения равного размера прежде, чем заменить переменную. Например,
a = rand(100e6,1) % 800 MB array b = rand(100e6,1) % New 800 MB array Error using rand Out of memory. Type HELP MEMORY for your options. clear a a = rand(100e6,1) % New 800 MB array