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

В этой теме объясняется несколько методов эффективного использования памяти в MATLAB®.

Использование подходящего хранилища данных

MATLAB предоставляет вам различные размеры классов данных, такие как double и uint8поэтому вам не нужно использовать большие классы для хранения небольших сегментов данных. Например, для хранения 1000 маленьких беззнаковых целочисленных значений с помощью uint8 требуется на 7 КБ меньше памяти класс, чем с double.

Используйте соответствующий числовой класс

Числовой класс, который вы должны использовать в MATLAB, зависит от ваших предполагаемых действий. Класс по умолчанию double обеспечивает лучшую точность, но требует 8 байт на элемент памяти для хранения. Если вы намерены выполнить сложную математику, такую как линейная алгебра, необходимо использовать класс с плавающей точкой, такой как double или single. The single для класса требуется всего 4 байта. Существуют некоторые ограничения на то, что вы можете сделать со single класс, но поддерживаются большинство операций MATLAB Math.

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

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

Уменьшите объем накладных расходов при хранении данных

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

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

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

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

Также обратите внимание, что хотя MATLAB хранит числовые массивы в смежной памяти, это не относится к структурам и массивам ячеек. Для получения дополнительной информации смотрите Как 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  

Можно видеть, что для хранения этого массива требуется только около 24 КБ в виде разреженных, но приблизительно 8 Мб в виде полной матрицы. В целом, для разреженного двойного массива с nnz ненулевые элементы и ncol столбцы, требуемая память:

  • 16 * nnz + 8 * ncol + 8 байт (на 64-разрядной машине)

Обратите внимание, что MATLAB поддерживает большинство, но не все, математических операций на разреженных массивах.

Избегайте временных копий данных

Можно значительно уменьшить объем необходимой памяти, избегая создания ненужных временных копий данных.

Избегайте создания временных массивов

Избегайте создания больших временных переменных, а также делайте это практикой, чтобы очистить временные переменные, когда они больше не нужны. Например, этот код создает массив нулей, сохраненных как временная переменная A, а затем преобразует A с одной точностью:

A = zeros(1e6,1);
As = single(A);

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

A = zeros(1e6,1,'single');

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

Используйте вложенные функции, чтобы передать меньше аргументов

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

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

function myfun
A = magic(500);
setrowval(400,0)
disp('The new value of A(399:401,1:10) is')
A(399:401,1:10)

    function setrowval(row,value)
    A(row,:) = value;
    end
    
end

Восстановление использованной памяти

Один из простых способов увеличить объем доступной памяти - очистить большие массивы, которые вы больше не используете.

Периодически сохраняйте большие данные на диск

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

Очистить старые переменные от памяти, когда больше не нужно

Когда вы работаете с очень большим набором данных неоднократно или в интерактивном режиме, сначала очистите старую переменную, чтобы освободить пространство для новой переменной. В противном случае MATLAB требует временного хранения равного размера перед переопределением переменной. Для примера,

a = rand(1e5);
b = rand(1e5);
Out of memory.

More information
 
 
clear a
a = rand(1e5);              % New array 

Похожие темы