exponenta event banner

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

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

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

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

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

Числовой класс, который должен использоваться в MATLAB, зависит от предполагаемых действий. Класс по умолчанию double обеспечивает наилучшую точность, но для хранения требуется 8 байт на элемент памяти. Если предполагается выполнить сложную математику, такую как линейная алгебра, необходимо использовать класс с плавающей запятой, такой как double или single. 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 

Связанные темы