Main Content

Control Inlining to Fine-Tune Performance and Readability of Generated Code

Inlining is an optimization technique that replaces a function call with the contents (body) of that function. Inlining eliminates the overhead of a function call, which can improve speed. Inlining can also create opportunities for further optimization of the generated C/C++ code.

However. depending on your application, too much code inlining can also have certain disadvantages:

  • Inlining can produce larger C/C++ code and reduce code readability. For example, suppose that you call a certain function foo many times in your source MATLAB® code. If the code generator always inlines foo, the generated code size increases because foo is inlined every time it is called. However, for this to happen, the call sites must be different. For example, inlining does not lead to large code size if foo is called several times inside a loop.

  • For non-inlined functions, stack space for variables local to the function is released when the function returns. For inlined functions, stack space remains occupied by the local variables even when the function returns. So, if you have limited RAM or stack space, you might want to restrict function inlining.

The code generator uses internal heuristics to determine whether to inline functions in the generated code. This help topic explains how to fine-tune these heuristics and generate code that meets the speed, readability, and stack space requirements of your application.

Control Inlining of a Specific MATLAB Function

To instruct the code generator to either always or never inline a certain MATLAB function, use the coder.inline('always') and coder.inline('never') directives inside the body of that function. To learn more about these directives, see coder.inline.

Alternatively, to control inlining at the call site, call a function using coder.inlineCall or coder.nonInlineCall. The coder.inlineCall and coder.nonInlineCall functions override any coder.inline directives in the body of the called function.

Control Inlining by Using Code Generation Settings

You might have different speed and readability requirements for the code generated for functions that you write and the code generated for MathWorks® functions. Certain code generation settings enable you to separately control the inlining behavior for these two parts of the generated code base and at the boundary between them. These settings apply to both MEX and standalone code generation.

Code Configuration ParameterDescriptionOptions

In a code configuration object: InlineBetweenUserFunctions

In the MATLAB Coder™ app: On the All Settings tab, Inline between user functions

Controls inlining behavior at all call sites where a function that you wrote calls another function that you wrote

'Always' | 'Speed' (default) | 'Readability' | 'Never'

In a code configuration object: InlineBetweenMathWorksFunctions

In the MATLAB Coder app: On the All Settings tab, Inline between MathWorks functions

Controls inlining behavior at all call sites where a MathWorks function calls another MathWorks function

'Always' | 'Speed' (default) | 'Readability' | 'Never'

In a code configuration object: InlineBetweenUserAndMathWorksFunctions

In the MATLAB Coder app: On the All Settings tab, Inline between user and MathWorks functions

Controls inlining behavior at all call sites where a function that you wrote calls a MathWorks function, or a MathWorks function calls a function that you wrote

'Always' | 'Speed' (default) | 'Readability' | 'Never'

Option descriptions:

  • 'Always': Always performs inlining at a call site.

  • 'Speed': Uses internal heuristics to determine whether to perform inlining at a call site. This setting usually leads to highly optimized code. This setting is the default setting.

  • 'Readability': Almost never inlines function calls, except for calls to very small functions. Preserves modularity of code without sacrificing too much speed, whenever possible. Results in highly readable code.

  • 'Never': Never inlines function calls. Results in maximum readability. This setting might significantly reduce the performance of the generated code.

Note

In certain cases, the code generator might not strictly follow the option you choose for an inlining parameter. For example, if the body of a MathWorks function contains the coder.inline('never') directive and you set InlineBetweenMathWorksFunctions to 'Always', the code generator gives preference to the coder.inline directive and does not inline that function. For more information, see Interaction Between Different Inlining Controls.

An Example Inlining Strategy

This is an example inlining strategy that balances the speed and readability of the generated code. You instruct the code generator to perform these actions simultaneously:

  • Preserve the modularity in the code that you write for better readability, even if that reduces the speed of the generated code. For this behavior, set InlineBetweenUserFunctions to 'Readability'.

  • Generate highly optimized code for MathWorks functions, even if that results in less readable code, because you are less likely to inspect this part of your code base. For this behavior, set InlineBetweenMathWorksFunctions to 'Speed'.

  • In the generated code, separate functions that you write and MathWorks functions so that the generated code does not look very different from your MATLAB code. For this behavior, set InlineBetweenUserAndMathWorksFunctions to 'Readability'.

Interaction Between Different Inlining Controls

  • The coder.inline('always') or coder.inline('never') directive placed inside the body of a MATLAB function overrides the effect of the global inlining controls, including the codegen options and the code configuration settings. See coder.inline.

    Certain MathWorks functions include a call to the coder.inline directive that affects how those functions interact with the global inlining settings. For example, if the body of a MathWorks function contains the coder.inline('never') directive and you set InlineBetweenMathWorksFunctions to 'Always', the code generator gives preference to the coder.inline directive and does not inline that function.

  • Calling a function using coder.inlineCall or coder.nonInlineCall overrides any coder.inline directives in the called MathWorks or user-written function, as well as any global inlining settings.

  • The -O disable:inline and -O enable:inline options of the codegen command override the individual values of the three code configuration parameters InlineBetweenUserFunctions, InlineBetweenMathWorksFunctions, and InlineBetweenUserAndMathWorksFunctions.

Example: Control Inlining at the Boundary Between Your Functions and MathWorks® Functions

This example shows how to control inlining behavior at all call sites where a function that you wrote calls a MathWorks function, or a MathWorks function calls a function that you wrote.

Define A Function That Calls MathWorks Functions

Define a MATLAB function useBessely that accepts a double array x as input, processes the input array by using the bessely function, and returns an array that has the same type and size as x.

type useBessely.m
function out = useBessely(x)
out = x + bessely(3,x);
end

Generate Code With Default Inlining Settings

Generate a static C++ library for the useBessely function. Specify the input to be a 1-by-100 double type. Use the default values for the inlining settings. These default values optimize the speed of the generated code. Use the -c flag that instructs the code generator to produce source code only and not build the source code.

codegen -c -lang:c++ -config:lib useBessely -args {zeros(1,100)} -report
Code generation successful: To view the report, open('codegen/lib/useBessely/html/report.mldatx')

Open the code generation report and inspect the generated code. Observe that no separate C++ function has been generated for the MathWorks function bessely. The code generator has inlined the code for the bessely function into the C++ useBessely function that is contained in the file useBessely.cpp.

Generate Code With Modified Inlining Settings

Define a code configuration object cfg for generating a static C++ library. Set the property InlineBetweenUserAndMathWorksFunctions to 'Never'. This setting instructs the code generator to separate the function that you wrote and the MathWorks functions in the generated code. As a result, the generated C++ code is less efficient but more readable than the inlined code.

cfg = coder.config('lib');
cfg.TargetLang = 'C++';
cfg.InlineBetweenUserAndMathWorksFunctions = 'Never';

Generate code by using cfg as the code configuration object. Specify the input to be a 1-by-100 double type. Use the -c flag that instructs the code generator to produce source code only and not build the source code.

codegen -c -config cfg useBessely -args {zeros(1,100)} -report
Code generation successful: To view the report, open('codegen/lib/useBessely/html/report.mldatx')

Open the code generation report and inspect the generated code. The C++ function useBessely now calls another C++ function coder::bessely that contains the code generated for the MathWorks function bessely. As a result, the generated C++ useBessely function looks similar to the MATLAB useBessely function that you wrote.

type codegen/lib/useBessely/useBessely.cpp
//
// File: useBessely.cpp
//
// MATLAB Coder version            : 24.1
// C/C++ source code generated on  : 12-Feb-2024 21:02:25
//

// Include Files
#include "useBessely.h"
#include "bessely.h"
#include "rt_nonfinite.h"

// Function Definitions
//
// Arguments    : const double x[100]
//                creal_T out[100]
// Return Type  : void
//
void useBessely(const double x[100], creal_T out[100])
{
  coder::bessely(x, out);
  for (int i{0}; i < 100; i++) {
    out[i].re += x[i];
  }
}

//
// File trailer for useBessely.cpp
//
// [EOF]
//

See Also

| | | | | |

Related Topics