Main Content

Generate Code That Preserves Entry-Point Input Data

Since R2024b

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:

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 or coder.EmbeddedCodeConfig object, set the PreserveInputData property to true.

  • 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

| |

Related Topics