Стратегии эффективного использования памяти

Способы уменьшить необходимый объем памяти

Источник многих "из памяти" проблемы часто включает анализ или обработку существующего большого набора данных такой как в файле или базе данных. Это требует обеспечения всех или части набора данных в процесс MATLAB. Следующие методы имеют дело с минимизацией необходимой памяти во время этого этапа.

Загрузите только столько данные, сколько вам нужно

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

FileType Частичная загрузка
Matfile

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

Текст

Используйте функцию textscan, чтобы получить доступ к частям файла крупного текста путем чтения только выбранных столбцов и строк. Если вы задаете количество строк или повторный номер формата с textscan, MATLAB вычисляет точный объем памяти, требуемый заранее.

Двоичный файл

Можно использовать низкоуровневые функции ввода-вывода двоичного файла, такие как fread, к частям доступа любого файла, который имеет известный формат. Для двоичных файлов неизвестного формата попытайтесь использовать размещение в ОЗУ с функцией memmapfile.

Отобразите, 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. Следующее является списком числовых классов, требования к памяти (в байтах), и поддерживаемые операции.

Класс (тип данных)БайтыПоддерживаемые операции
single4Большая часть математики
double8Вся математика
logical1Логические/условные операции
int8, uint81Арифметика и некоторые простые функции
int16, uint162Арифметика и некоторые простые функции
int32, uint324Арифметика и некоторые простые функции
int64, int648Арифметика и некоторые простые функции

Сокращение суммы издержек, храня данные

Массивы MATLAB (реализованный внутренне как mxArrays) требуют, чтобы комната сохранила метаинформацию о данных в памяти, такой как тип, размерности и атрибуты. Это берет приблизительно 80 байтов за массив. Эти издержки только становятся проблемой, когда у вас есть большое количество (например, сотни или тысячи) маленького mxArrays (например, скаляры). Списки команд whos память, используемая переменными, но, не включают эти издержки.

Поскольку простые числовые массивы (включение того mxArray) имеют наименее служебное, необходимо использовать их по мере возможности. Когда данные являются слишком комплексными, чтобы сохранить в простом массиве (или матрица), можно использовать другие структуры данных.

Массивы ячеек состоят из отдельного mxArrays для каждого элемента. В результате массивы ячеек со многими маленькими элементами имеют большие издержки.

Структуры требуют подобной суммы издержек на поле (см. Заголовки Массивов). Структуры со многими полями и маленьким содержимым имеют большие издержки и должны избежаться. Большой массив структур с полями числового скаляра требует намного большей памяти, чем структура с полями, содержащими большие числовые массивы.

Также обратите внимание на это, в то время как MATLAB хранит числовые массивы в непрерывной памяти, дело обстоит не так для структур и массивов ячеек.

Импортирование данных к соответствующему классу 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);

Долгосрочное использование (только Windows Systems)

На 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 
Для просмотра документации необходимо авторизоваться на сайте