Избегайте ненужных копий данных

Передача значений функциям

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

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

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

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

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

A = rand(1e7,1);
B = f1(A);

Функция f1 умножает каждый элемент в массиве входа X по 1.1 и присваивает результат переменной Y.

function Y = f1(X)
Y = X.*1.1; % X is a shared copy of A
end

Поскольку функция не изменяет вход значения, локальная переменная X и переменной A в рабочей области вызывающего абонента совместно использовать данные. После f1 выполняет, значения, присвоенные A не изменились. Переменная B в рабочая область вызывающего абонента содержится результат поэлементного умножения. Вход передается значением. Однако копия при вызове не выполняется f1.

Функция f2 изменяет свою локальную копию входной переменной, в результате чего локальная копия будет отменена с входом A. Значение X теперь функция является независимой копией переменного входа A в рабочей области вызывающего абонента. Когда f2 возвращает результат в рабочую область вызывающего абонента - локальную переменную X уничтожается.

A = rand(1e7,1);
B = f2(A);
function Y = f2(X)
X = X.*1.1; % X is an independent copy of A
Y = X;      % Y is a shared copy of X
end

Передача входных параметров в виде выражений MATLAB

Можно использовать значение, возвращенное из функции, как входной параметр к другой функции. Для примера используйте rand функция для создания входов функции f2 непосредственно.

B = f2(rand(1e7,1));

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

Назначение по месту

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

A = f2(A);

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

MATLAB может применять оптимизацию памяти при определенные обстоятельства. Рассмотрим следующий пример. The canBeOptimized функция создает большой массив случайных чисел в переменной A. Затем вызывается локальная функция fLocal, прохождение A в качестве входов и присвоения выходов локальной функции тому же имени переменной.

function canBeOptimized
A = rand(1e7,1);
A = fLocal(A);
end
function X = fLocal(X)
X = X.*1.1;
end

Поскольку вызов локальной функции, A = fLocal(A), присваивает выход переменной AMATLAB не нужно сохранять исходное значение A во время выполнения функции. Изменения, внесенные в X внутри fLocal не приводят к копированию данных. Назначение X = X.*1.1 изменяет X на месте, без выделения нового массива для результата умножения. Удаление копии в локальной функции сохраняет память и улучшает скорость выполнения для больших массивов.

Однако MATLAB не может применить эту оптимизацию, если назначение в локальной функции требует индексации массива. Для примера измените массив ячеек, созданный в updateCells требует индексации в массив X в локальной функции gLocal. Закольцованное назначение в форме X{i} = X{i}*1.1 создает копию данных в X{i}. Для каждого элемента массива ячеек существует две копии в рабочей области gLocal.

function updateCells
C = num2cell(rand(1e7,1));
C = gLocal(C);
end
function X = gLocal(X)
for i = 1:length(X)
    X{i} = X{i}*1.1;
end
end

Действуют несколько дополнительных ограничений. MATLAB не может применить оптимизацию памяти, когда можно использовать переменную после того, как функция выдает ошибку. Поэтому эта оптимизация не применяется в скриптах, в командной строке, в вызовах к eval, или кодировать внутри try/catch блоки. Кроме того, MATLAB не применяет оптимизацию памяти, когда исходная переменная непосредственно доступна во время выполнения вызываемой функции. Для примера, если fLocal была вложенной функцией, MATLAB не смог применить оптимизацию, поскольку переменные могут использоваться совместно с родительской функцией. Наконец, MATLAB не применяет оптимизацию памяти, когда назначенная переменная объявлена глобальной или стойкой.

Отладочный код, который использует назначение по месту

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

Для примера эта функция имеет несоответствие в размерностях переменных A и B.

function A  = inPlace
A = rand(100);
B = rand(99);
dbstop if error
A = A.*B;
end

Выполнение функции выдает ошибку и останавливается в отладчике.

inPlace
Matrix dimensions must agree.

Error in inPlace (line 5)
A = A.*B;
 
5   A = A.*B;

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

K>> A
Variable "A" is inaccessible. When a variable appears on both sides of
an assignment statement, the variable may become temporarily
unavailable during processing.

Чтобы получить большую гибкость при отладке, рефаксируйте код, чтобы удалить назначение по месту. Например, присвойте результат другой переменной.

function A  = inPlace
A = rand(100);
B = rand(99);
dbstop if error
% Assign result to C indtead of A
C = A.*B;
A = C;
end

Тогда переменная A видна во время работы отладчика.

Зачем семантика Pass-By-Value

MATLAB использует семантику передачи значений при передаче аргументов функциям и возвращении значений из функций. В некоторых случаях pass-by-value приводит к тому, что копии исходных значений создаются в вызываемой функции. Однако семантика pass-by-value предоставляет определенные преимущества.

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

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

Указатель Объектов

Существуют специальные виды объектов, называемые handles. Все переменные, которые содержат копии одного указателя, могут получить доступ и изменить один и тот же базовый объект. Объекты указатель применяются в специальных обстоятельствах, когда объект представляет физический объект, такой как окно, график, устройство или человека, а не математический объект, такой как число или матрица.

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

Для получения дополнительной информации о значениях и указателях смотрите Сравнение классов указателей и значений и Какой тип класса использовать.

См. также

Похожие темы