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

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

При вызывании функции с входными параметрами, 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 может применить оптимизацию памяти при определенных обстоятельствах. Рассмотрите следующий пример. 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), присваивает выход переменной A, MATLAB не должен сохранять исходное значение 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 отображается в то время как в отладчике.

Почему семантика передачи значением

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

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

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

Обработайте объекты

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

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

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

Смотрите также

Похожие темы