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, thereby improving speed.
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 inlinesfoo
, the generated code size increases becausefoo
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 iffoo
is called several times inside a loop.For out-of-line 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
.
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 Parameter | Description | Options |
---|---|---|
In a code configuration object:
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:
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:
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')
orcoder.inline('never')
directive placed inside the body of a MATLAB function overrides the effect of the global inlining controls, including thecodegen
options and the code configuration settings. Seecoder.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 thecoder.inline('never')
directive and you setInlineBetweenMathWorksFunctions
to'Always'
, the code generator gives preference to thecoder.inline
directive and does not inline that function.The
-O disable:inline
and-O enable:inline
options of thecodegen
command override the individual values of the three code configuration parametersInlineBetweenUserFunctions
,InlineBetweenMathWorksFunctions
, andInlineBetweenUserAndMathWorksFunctions
.
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 reault, 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 : 5.6 // C/C++ source code generated on : 03-Mar-2023 05:02:50 // // 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
coder.inline
| codegen
| coder.CodeConfig
| coder.EmbeddedCodeConfig
| coder.MexCodeConfig