Avoid Unnecessary Copies of Data
Passing Values to Functions
When calling a function with input arguments, MATLAB® copies the values from the calling function’s workspace into the parameter variables in the function being called. However, MATLAB applies various techniques to avoid making copies of these values when it is not necessary.
MATLAB does not provide a way to define a reference to a value, as in languages like C++. Instead, MATLAB allows multiple output as well as multiple input parameters so that you know what values are going into a function and what values are coming out of the function.
Copy-on-Write
If a function does not modify an input argument, MATLAB does not make a copy of the values contained in the input variable.
For example, suppose that you pass a large array to a function.
A = rand(1e7,1); B = f1(A);
The function f1
multiplies each element in the input array
X
by 1.1
and assigns the result to the
variable Y
.
function Y = f1(X) Y = X.*1.1; % X is a shared copy of A end
Because the function does not modify the input values, the local variable
X
and the variable A
in the caller's
workspace share the data. After f1
executes, the values
assigned to A
have not changed. The variable
B
in the caller's workspace contains the result of the
element-wise multiplication. The input is passed by value. However, no copy is
made when calling f1
.
The function f2
does modify its local copy of the input
variable, causing the local copy to be unshared with input A
.
The value of X
in the function is now an independent copy of
the input variable A
in the caller's workspace. When
f2
returns the result to the caller's workspace, the
local variable X
is destroyed.
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
Passing Inputs as MATLAB Expressions
You can use the value returned from a function as an input argument to another
function. For example, use the rand
function to create the
input for the function f2
directly.
B = f2(rand(1e7,1));
The only variable holding the value returned by rand
is the
temporary variable X
in the workspace of the function
f2
. There is no shared or independent copy of these
values in the caller's workspace. Directly passing function outputs saves the
time and memory required to create a copy of the input values in the called
function. This approach makes sense when the input values are not used
again.
Assigning In-Place
When you do not need to preserve the original input values, you can assign the output of a function to the same variable that you provided as input.
A = f2(A);
In-place assignment follows the copy-on-write behavior described previously: modifying the input variable values results in a temporary copy of those values.
MATLAB can apply memory optimizations under certain conditions. Consider
the following example. The canBeOptimized
function creates a
large array of random numbers in the variable A
. Then it
calls the local function fLocal
, passing A
as the input, and assigning the output of the local function to the same
variable name.
function canBeOptimized A = rand(1e7,1); A = fLocal(A); end function X = fLocal(X) X = X.*1.1; end
Because the call to the local function, A = fLocal(A)
,
assigns the output to the variable A
, MATLAB does not need to preserve the original value of
A
during execution of the function. Modifications made to
X
inside fLocal
do not result in a
copy of the data. The assignment X = X.*1.1
modifies
X
in place, without allocating a new array for the result
of the multiplication. Eliminating the copy in the local function saves memory
and improves execution speed for large arrays.
However, MATLAB cannot apply this optimization if the assignment in the local
function requires array indexing. For example, modifying the cell array created
in updateCells
requires indexing into X
in
the local function gLocal
. For every loop iteration
i
, the looped assignment in the form X{i} =
X{i}*1.1
results in a temporary variable the same size as
X{i}
for evaluating and storing the value of
X{i}*1.1
. MATLAB destroys the temporary variable after assigning its value to
X{i}
.
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
Several additional restrictions apply. MATLAB cannot apply memory optimization when it is possible to use the
variable after the function throws an error. Therefore, this optimization is not
applied in scripts, on the command line, in calls to eval
, or to code inside
try/catch
blocks. Also, MATLAB does not apply memory optimization when the original variable is
directly accessible during execution of the called function. For example, if
fLocal
was a nested function, MATLAB could not apply the optimization because variables can be shared
with the parent function. Finally, MATLAB does not apply memory optimization when the assigned variable is
declared as global or persistent.
Debugging Code That Uses In-Place Assignment
When MATLAB applies in-place optimization to an assignment statement, the variable on the left side of the assignment is set to a temporary state that makes it inaccessible before MATLAB executes the right side of the assignment statement. If MATLAB stops in the debugger before the result of executing the right-side of the statement has been assigned to the variable, examining the left-side variable can produce an error indicating that the variable is unavailable.
For example, this function has a mismatch in the dimensions of variables
A
and B
.
function A = inPlace A = rand(100); B = rand(99); dbstop if error A = A.*B; end
Executing the function throws an error and stops in the debugger.
inPlace
Arrays have incompatible sizes for this operation. Error in inPlace (line 5) A = A.*B;
Attempting to see the value of the variable A
while in
debug mode results in an error because the variable is temporarily
unavailable.
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.
To gain more flexibility when debugging, refactor your code to remove the in-place assignment. For example, assign the result to another variable.
function A = inPlace A = rand(100); B = rand(99); dbstop if error % Assign result to C instead of A C = A.*B; A = C; end
Then the variable A is visible while in the debugger.
Why Pass-by-Value Semantics
MATLAB uses pass-by-value semantics when passing arguments to functions and returning values from functions. In some cases, pass-by-value results in copies of the original values being made in the called function. However, pass-by-value semantics provides certain advantages.
When calling functions, you know that the input variables are not modified in the caller's workspace. Therefore, you do not need to make copies of inputs inside a function or at a call site just to guard against the possibility that these values might be modified. Only the variables assigned to returned values are modified.
Also, you avoid the possibility of corrupting workspace variables if an error occurs within a function that has been passed a variable by reference.
Handle Objects
There are special kinds of objects called handles. All variables that hold copies of the same handle can access and modify the same underlying object. Handle objects are useful in specialized circumstances where an object represents a physical object such as a window, plot, device, or person rather than a mathematical object like a number or matrix.
Handle objects derive from the handle
class, which provides
functionality such as events and listeners, destructor methods, and support for
dynamic properties.
For more information about values and handles, see Comparison of Handle and Value Classes and Which Kind of Class to Use.