Generate Code That Preserves Entry-Point Input Data - MATLAB & Simulink (original) (raw)
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 argumentx
to the function calleeFunc
, each function workspace has its own copy of x
. Even ifcalleeFunc
directly modifies its input argumentx
, the value of x
in the workspace ofcallerFunc
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 callspreserveInputDataTest
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 ofx
in the workspace of its caller.
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 inputx
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 or coder.EmbeddedCodeConfig object, set the
PreserveInputData
property totrue
. - In the MATLAB Coderâ„¢ app, on the Speed tab, select thePreserve input data for entry-point functions check box.
For example, regenerate code for the preserveInputDataTest
function with the PreserveInputData
configuration property set totrue
.
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