В этой теме объясняется несколько методов эффективного использования памяти в MATLAB®.
MATLAB предоставляет вам различные размеры классов данных, такие как double
и uint8
поэтому вам не нужно использовать большие классы для хранения небольших сегментов данных. Например, для хранения 1000 маленьких беззнаковых целочисленных значений с помощью uint8
требуется на 7 КБ меньше памяти класс, чем с
double
.
Числовой класс, который вы должны использовать в MATLAB, зависит от ваших предполагаемых действий. Класс по умолчанию double
обеспечивает лучшую точность, но требует 8 байт на элемент памяти для хранения. Если вы намерены выполнить сложную математику, такую как линейная алгебра, необходимо использовать класс с плавающей точкой, такой как double
или single
. The single
для класса требуется всего 4 байта. Существуют некоторые ограничения на то, что вы можете сделать со single
класс, но поддерживаются большинство операций MATLAB Math.
Если вам просто нужно провести простую арифметику и вы представляете исходные данные как целые числа, можно использовать целочисленные классы в MATLAB. Ниже приведен список числовых классов, требований к памяти (в байтах) и поддерживаемых операций.
Класс (тип данных) | Байты | Поддерживаемые операции |
---|---|---|
single | 4 | Большая часть математики |
double | 8 | Вся математика |
logical | 1 | Логические/условные операции |
int8, uint8 | 1 | Арифметические и некоторые простые функции |
int16, uint16 | 2 | Арифметические и некоторые простые функции |
int32, uint32 | 4 | Арифметические и некоторые простые функции |
int64, int64 | 8 | Арифметические и некоторые простые функции |
Массивы MATLAB (реализованы внутренне как mxArrays
) требуется комната для хранения метаинформации о данных в памяти, таких как тип, размерности и атрибуты. Это занимает около 104 байт на массив. Эти накладные расходы становятся проблемой только, когда у вас есть большое количество (например, сотни или тысячи) малых 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
Можно видеть, что для хранения этого массива требуется только около 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