Generate Code That Preserves Entry-Point Input Data
In C/C++, inputs to functions can be passed either by copy or by reference. However, in MATLAB®, function inputs are always passed by copy. This can sometimes cause difference in behavior between a MATLAB function and the C/C++ code generated from that function.
Suppose that you call the generated entry-point function from your custom C/C++ code. If the generated code directly modifies one of its input arguments that is passed by reference, the value of this argument in the scope of the caller also gets modified. By contrast, in MATLAB execution, the input data in the caller's workspace is always preserved because function inputs in the MATLAB language are always passed by copy. This topic explains when the generated code might pass inputs by reference, its performance benefits, and how to configure code generation to protect your input data.
Passing Inputs to MATLAB Functions
In MATLAB, when you call a function, the input arguments are passed by copy.
Therefore, when a function callerFunc
passes an input argument
x
to the function calleeFunc
, each function
workspace has its own copy of x
. Even if
calleeFunc
directly modifies its input argument
x
, the value of x
in the workspace of
callerFunc
remains unchanged. See Base and Function Workspaces.
For example, consider the function preserveInputDataTest
that sets
the fifth element of the input array x
to 0
before
computing the
output.
function y = preserveInputDataTest(x) x(5) = 0; disp("Value of x(5) in callee workspace is: " + x(5)) y = x' * x; end
Define another function callerFunction
that calls
preserveInputDataTest
with an input array of
ones.
function callerFunction x = ones(1,10); disp("Value of x(5) in caller workspace is: " + x(5)) preserveInputDataTest(x); end
At the command line, call callerFunction
. Observe that the
function preserveInputDataTest
did not modify the value of
x
in the workspace of its
caller.
callerFunction
Value of x(5) in caller workspace is: 1 Value of x(5) in callee workspace is: 0
Passing Inputs to Generated Entry-Point Functions
The generated entry-point functions, unlike MATLAB, might pass input data by reference. This happens primarily because of two reasons:
In the C/C++ language, certain types of data (like arrays) can be passed by reference only.
Passing data by reference reduces the number of data copies, thereby reducing memory usage and execution time. See Avoid Data Copies of Function Inputs in Generated Code and Pass Structure Arguments by Reference or by Value in Generated Code.
However, passing entry-point input arguments by reference might unexpectedly modify your input data. Suppose that you call the generated entry-point function from your custom C/C++ code. If the generated code directly modifies one of its input arguments that is passed by reference, the value of this argument in the scope of the caller also gets modified.
For example, generate code for the preserveInputDataTest
function
using the codegen
command. To simplify the
appearance of the generated code, set the InstructionSetExtensions
configuration property to "None"
. Specify the type of the input
x
to be double vectors of size 1024.
cfg = coder.config("lib"); cfg.InstructionSetExtensions = "None"; codegen -config cfg preserveInputDataTest -args ones(1,1024) -report
Examine the generated entry-point function.
void preserveInputDataTest(double x[1024], double y[1048576])
{
int i;
int i1;
x[4] = 0.0;
for (i = 0; i < 1024; i++) {
for (i1 = 0; i1 < 1024; i1++) {
y[i1 + (i << 10)] = x[i1] * x[i];
}
}
}
In the generated function, the input double x[1024]
is passed by
reference. The function body contains the line x[4] = 0.0;
that
directly modifies this input, thereby modifying the data in the caller's scope as well.
Generating Code That Preserves Entry-Point Input Data
If you want to protect your input data from modification when the generated code is called, you can do one of these actions:
In a
coder.CodeConfig
orcoder.EmbeddedCodeConfig
object, set thePreserveInputData
property totrue
.In the MATLAB Coder™ app, on the Speed tab, select the Preserve input data for entry-point functions check box.
For example, regenerate code for the preserveInputDataTest
function with the PreserveInputData
configuration property set to
true
.
cfg = coder.config("lib"); cfg.PreserveInputData = true; cfg.InstructionSetExtensions = "None"; codegen -config cfg preserveInputDataTest -args ones(1,1024) -report
Examine the generated entry-point function.
void preserveInputDataTest(const double x[1024], double y[1048576])
{
double b_x[1024];
int i;
int i1;
memcpy(&b_x[0], &x[0], 1024U * sizeof(double));
b_x[4] = 0.0;
for (i = 0; i < 1024; i++) {
for (i1 = 0; i1 < 1024; i1++) {
y[i1 + (i << 10)] = b_x[i1] * b_x[i];
}
}
}
This time, the generated code first copies the input x
into a
local variable b_x
and then performs the subsequent computations
using b_x
. This code pattern preserves the input data that you supply
to the generated preserveInputDataTest
entry-point function.
Usage Notes
If you enable the Preserve input data for entry-point
functions (PreserveInputData
) configuration setting,
the generated code might include extra copies of the input data. If you pass
large-size data, this behavior might increase the execution time and memory use of
the generated code.
If you generate code for a MATLAB entry-point function that uses the same variable as both an input and
an output, the code generator does not preserve this input data even when you enable
the Preserve input data for entry-point functions
(PreserveInputData
) configuration setting. See Avoid Data Copies of Function Inputs in Generated Code.
See Also
codegen
| coder.CodeConfig
| coder.EmbeddedCodeConfig