Как MATLAB выделяет память

Выделение памяти для массивов

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

Примечание

Любая информация о том, как программное обеспечение MATLAB обрабатывает данные внутренне, подвержена изменениям в будущих релизах.

Создание и изменение массивов

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

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

Если вы удаляете элементы из существующего массива, MATLAB сохраняет устройство хранения данных памяти непрерывным путем удаления удаленных элементов, и затем уплотнения его устройства хранения данных в исходной ячейке памяти.

Работа с Большими наборами данных.  Если вы работаете с большими наборами данных, необходимо быть осторожными при увеличении размера массива, чтобы не получать ошибки, вызванные недостаточно памятью. Если вы расширяете массив вне доступной непрерывной памяти о его исходном местоположении, MATLAB должен сделать копию массива и установить эту копию на новое значение. Во время этой операции существует две копии исходного массива в памяти. Это временно удваивает объем памяти, требуемый для массива, и увеличивает риск вашей программы, исчерпывающей память во время выполнения. Лучше предварительно выделить достаточную память для самого большого потенциального размера массива в запуске. Смотрите Предварительное выделение.

Копирование массивов

Внутренне, несколько переменных могут указать на тот же блок данных, таким образом совместно использовав что значение массива. Когда вы копируете переменную в другую переменную (например, B = A), MATLAB делает копию ссылки на массив, но не сам массив. Пока вы не изменяете содержимое массива, нет никакой потребности сохранить больше чем одну копию его. Если вы действительно изменяете какие-либо элементы массива, MATLAB делает копию массива и затем изменяет ту копию.

Этот пример использует функцию memory, чтобы продемонстрировать, как MATLAB обрабатывает копирование массивов. memory доступен только в системах Windows®.

Запустите путем создания простого скрипта memUsed.m, чтобы отобразиться, сколько памяти используется процессом MATLAB. Поместите эти две строки кода в скрипт.

[usr, sys] = memory;
usr.MemUsedMATLAB

Получите начальное чтение того, сколько памяти используется вашим процессом MATLAB:

format short eng;
memUsed
ans =
   295.4977e+006

Создайте 2000 2000 числовой массив A. Это использует приблизительно 32 МБ памяти:

A = magic(2000);
memUsed
ans =
   327.6349e+006

Сделайте копию массива A в B. Как нет никакой потребности иметь две копии данных массива, MATLAB только делает копию ссылки на массив. Это не требует никакой значительной дополнительной памяти:

B = A;
memUsed
ans =
   327.6349e+006

Теперь измените B путем создания его одной половиной его первоначального размера (то есть, установите 1 000 строк пустеть). Это требует, чтобы MATLAB сделал копию, по крайней мере, первых 1 000 строк массива A и присвоение, которые копируют в B:

B(1001:2000,:) = [];
format short;   size(B)
ans =
        1000        2000

Проверяйте память, используемую снова. Даже при том, что B значительно меньше, чем это было первоначально, объем памяти, используемый процессом MATLAB, увеличился приблизительно на 16 Мбайт (1/2 32 Мбайт, первоначально требуемых для A), потому что B больше не мог оставаться как только ссылка на A:

format short eng;   memUsed
ans =
   343.6421e+006

Заголовки массивов

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

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

Например, возьмите скалярный массив структур S1, имеющий поля R, G и B. Каждое поле размера 100 50 требует, чтобы один заголовок массивов описал полную структуру, один заголовок для каждого уникального имени поля и один заголовок на поле для массива структур 1 на 1. Это делает в общей сложности семь заголовков массивов для целой структуры данных:

S1.R(1:100,1:50)
S1.G(1:100,1:50)
S1.B(1:100,1:50)

С другой стороны, возьмите 100 50 массив структур S2, в котором каждый элемент имеет скалярные поля R, G и B. В этом случае вам нужен один заголовок массивов, чтобы описать полную структуру, один для каждого уникального имени поля, и один на поле для каждого из 5 000 элементов структуры, делая в общей сложности 15 004 заголовка массивов для целой структуры данных:

S2(1:100,1:50).R
S2(1:100,1:50).G
S2(1:100,1:50).B

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

См. “Массивы ячеек” и “структуры” под структурами данных и памятью.

Использование памяти, о котором Сообщают, кто Функция.  Функция whos отображает объем памяти, использованный любой переменной. По причинам простоты whos сообщает, что только память раньше хранила фактические данные. Это не сообщает об устройстве хранения данных для заголовка массивов, например.

Аргументы функции

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

В примере ниже, функциональный myfun изменяет значение массива, переданного в него. MATLAB делает копию в память о массиве указанной A, устанавливает переменную X как ссылку на этот новый массив, и затем обнуляет одну строку X. Массив, на который ссылается A, остается неизменным:

A = magic(500);
myfun(A);

function myfun(X)
X(400,:) = 0;

Если для функции вызова нужно измененное значение массива, это передало myfun, необходимо возвратить обновленный массив как вывод вызванной функции, как показано сюда для переменной A:

A = magic(500);
A = myfun(A);
sprintf('The new value of A is %d', A)

function Y = myfun(X)
X(400,:) = 0;
Y = X;

Структуры данных и память

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

Числовые массивы

MATLAB требует 1, 2, 4, или 8 байтов хранить 8-битные, 16-битные, 32-битные, и 64-битные целые числа со знаком и беззнаковое целое, соответственно. Для чисел с плавающей запятой MATLAB использует 4 или 8 байтов для типов double и single. Чтобы сохранить память при работе с числовыми массивами, MathWorks® рекомендует, чтобы вы использовали самый маленький целочисленный или тип с плавающей точкой, который содержит ваши данные без переполнения. Для получения дополнительной информации смотрите Числовые Типы.

Комплексные массивы

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

Разреженные матрицы

Лучше хранить матрицы значениями, которые являются в основном нулем в разреженном формате. Разреженные матрицы могут использовать меньше памяти и могут также быть быстрее, чтобы управлять, чем полные матрицы. Можно преобразовать полную матрицу в разреженный формат с помощью функции sparse.

Сравните две матрицы 1000 на 1000: X, матрица удваивается с 2/3 ее равных нулю элементов; и Y, разреженная копия X. Следующий пример показывает, что разреженная матрица требует приблизительно вдвое меньше памяти:

whos
  Name      Size                   Bytes  Class

  X      1000x1000               8000000  double array
  Y      1000x1000               4004000  double array (sparse)

Массивы ячеек

В дополнение к хранению данных массивы ячеек требуют, чтобы определенное количество дополнительной памяти хранило информацию, описывающую каждую ячейку. Эта информация зарегистрирована в header, и существует один заголовок для каждой ячейки массива. Можно определить объем памяти, требуемый для заголовка массива ячеек путем нахождения количества байтов использованным ячейкой 1 на 1, которая не содержит данных, как показано ниже для 32-битной системы:

A = {[]};      % Empty cell array

whos A
  Name      Size            Bytes  Class    Attributes

  A         1x1                60  cell

В этом случае MATLAB показывает количество байтов, требуемых для каждого заголовка в массиве ячеек в 32-битной системе быть 60. Это - размер заголовка, который используется во всех 32-битных примерах в этом разделе. Для 64-битных систем размер заголовка принят, чтобы быть 112 байтов в этой документации. Можно найти правильный размер заголовка в 64-битной системе с помощью метода, только показанного для 32 битов.

Чтобы предсказать размер целого массива ячеек, умножьте номер, который вы вывели для заголовка общим количеством ячеек в массиве, и затем добавляете в это количество байтов, требуемых для данных, которые вы намереваетесь хранить в массиве:

(header_size x number_of_cells) + data

Таким образом, 10 20 массив ячеек, который содержит 400 байтов данных, потребовал бы 22 800 байтов памяти в 64-битной системе:

(112 x 200) + 400 = 22800

Примечание

В то время как числовые массивы должны храниться в непрерывной памяти, структуры и массивы ячеек не делают.

Пример 1 – Выделение памяти для Массива ячеек.  Следующее 4 1 массив ячеек записывает фирменный знак, размер экрана, цену и распивочное состояние для трех ноутбуков:

Laptops = {['SuperrrFast 89X', 'ReliablePlus G5', ...
            'UCanA4dIt 140L6']; ...
           [single(17), single(15.4), single(14.1)]; ...
           [2499.99, 1199.99, 499.99]; ...
           [true, true, false]};

В 32-битной системе один только заголовок массива ячеек требует 60 байтов за ячейку:

4 cells * 60 bytes per cell = 240 bytes for the cell array

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

45 characters * 2 bytes per char = 90 bytes
 3 doubles * 8 bytes per double = 24 bytes
 3 singles * 4 bytes per single = 12 bytes
 3 logicals * 1 byte per logical = 3 bytes

90 + 24 + 12 + 3 = 129 bytes for the data

Добавьте эти два, и затем сравните свой результат с размером, возвращенным MATLAB:

240 + 129 = 369 bytes total

whos Laptops
  Name         Size            Bytes  Class    Attributes

  Laptops      4x1               369  cell 

Структуры

S.A = [];
B = whos('S');
B.bytes - 60
ans =
    64

Вычислите память, необходимую для массива структур можно следующим образом:

32-bit systems:  fields x ((60 x array elements) + 64) + data
64-bit systems:  fields x ((112 x array elements) + 64) + data

На 64-битной компьютерной системе 4 5 структура Clients с полями Address и Phone использует 4 608 байтов только для структуры:

2 fields x ((112 x 20) + 64) = 2 x (2240 + 64) = 4608 bytes

К той сумме необходимо добавить память, требуемую содержать данные, присвоенные каждому полю. Если вы присваиваете 25 векторов символов Address и 12 векторов символов к Phone в каждом элементе 4 5 массив Clients, вы используете 1 480 байтов для данных:

(25+12) characters * 2 bytes per char * 20 elements = 1480 bytes

Добавьте два, и вы видите, что целая структура использует 6 088 байтов памяти.

Пример 1 – Выделение памяти для Массива структур.  Вычислите объем памяти, который потребовался бы, чтобы хранить следующее 6 5 массив структур, имеющий следующие четыре поля в 32-битной системе:

A:  5-by-8-by-6 signed 8-bit integer array
B:  1-by-500 single array
C:  30-by-30 unsigned 16-bit integer array
D:  1-by-27 character array

Создайте массив:

A = int8(ones(5,8,6));
B = single(1:500);
C = uint16(magic(30));
D = 'Company Name: MathWorks';

s = struct('f1', A, 'f2', B, 'f3', C, 'f4', D);

for m=1:6
   for n=1:5
      s(m,n)=s(1,1);
   end
end

Вычислите объем памяти, требуемый для самой структуры, и затем для данных это содержит:

structure = fields x ((60 x array elements) + 64) =
            4 x ((60 x 30) + 64) = 7,456 bytes

data = (field1 + field2 + field3 + field4) x array elements =
       (240 + 2000 + 1800 + 54) x 30 = 122,820 bytes

Добавьте эти два, и затем сравните свой результат с размером, возвращенным MATLAB:

Total bytes calculated for structure s: 7,456 + 122,820 = 130,276

whos s
  Name      Size            Bytes  Class     Attributes

  s         6x5             130036  struct