Generate Code for Variable-Size Data - MATLAB & Simulink (original) (raw)
Variable-size data is data whose size might change at run time. You can use MATLAB® Coder™ to generate C/C++ code from MATLAB code that uses variable-size data. MATLAB supports bounded and unbounded variable-size data for code generation.Bounded variable-size data has fixed upper bounds. This data can be allocated statically on the stack or dynamically on the heap. Unbounded variable-size data does not have fixed upper bounds. This data must be allocated on the heap. By default, for MEX and C/C++ code generation, support for variable-size data is enabled and dynamic memory allocation is enabled for variable-size arrays whose size is greater than or equal to a configurable threshold.
Disable Support for Variable-Size Data
By default, for MEX and C/C++ code generation, support for variable-size data is enabled. You modify variable sizing settings from the project settings dialog box, the command line, or using dialog boxes.
Using the MATLAB Coder App
- To open the Generate dialog box, on theGenerate Code page, click theGenerate arrow
.
- Click More Settings.
- On the Memory tab, select or clear Enable variable-sizing.
At the Command Line
- Create a configuration object for code generation. For example, for a library:
cfg = coder.config('lib'); - Set the
EnableVariableSizing
option:
cfg.EnableVariableSizing = false; - Using the
-config
option, pass the configuration object tocodegen
:
Control Dynamic Memory Allocation
By default, dynamic memory allocation is enabled for variable-size arrays whose size is greater than or equal to a configurable threshold. You can modify dynamic memory allocation settings from the project settings dialog box or the command line.
Using the MATLAB Coder App
- To open the Generate dialog box, on theGenerate Code page, click theGenerate arrow
.
- Click More Settings.
- On the Memory tab, set Enable dynamic memory allocation to one of the following options:
Setting Action false Dynamic memory allocation is disabled. Variable-size data is allocated statically on the stack. true Dynamic memory allocation is enabled for variable-size arrays whose size is greater than or equal to theDynamic memory allocation threshold. Variable-size arrays whose size is less than this threshold are allocated on the stack. - Optionally, you can configure Dynamic memory allocation threshold to fine-tune memory allocation. If you set the value for Dynamic memory allocation threshold to
0
, variable-size data gets dynamically allocated on the heap.
At the Command Line
- Create a configuration object for code generation. For example, for a MEX function:
mexcfg = coder.config('mex'); - Set the
EnableDynamicMemoryAllocation
option:Setting Action mexcfg.EnableDynamicMemoryAllocation=false; Dynamic memory allocation is disabled. Variable-size data is allocated statically on the stack. mexcfg.EnableDynamicMemoryAllocation=true; Dynamic memory allocation is enabled for variable-size arrays whose size (in bytes) is greater than or equal to the value specified using theDynamicMemoryAllocationThreshold parameter. Variable-size arrays whose size is less than this threshold are allocated on the stack. - You can configure
DynamicMemoryAllocationThreshold
option, to fine tune memory allocation. If you setDynamicMemoryAllocationThreshold
to0
, variable-size data gets dynamically allocated on the heap. - Using the
-config
option, pass the configuration object tocodegen
:
codegen -config mexcfg foo
Generating Code for MATLAB Functions with Variable-Size Data
Here is a basic workflow that first generates MEX code for verifying the generated code and then generates standalone code after you are satisfied with the result of the prototype.
To work through these steps with a simple example, see Generate Code for a MATLAB Function That Expands a Vector in a Loop
- In the MATLAB Editor, add the compilation directive
%#codegen
at the top of your function.
This directive:- Indicates that you intend to generate code for the MATLAB algorithm
- Turns on checking in the MATLAB Code Analyzer to detect potential errors during code generation
- Address issues detected by the Code Analyzer.
In some cases, the MATLAB Code Analyzer warns you when your code assigns data a fixed size but later grows the data, such as by assignment or concatenation in a loop. If that data is supposed to vary in size at run time, you can ignore these warnings. - Generate a MEX function using codegen to verify the generated code. Use the following command-line options:
-args {coder.typeof...}
if you have variable-size inputs-report
to generate a code generation report
For example:
codegen -report foo -args {coder.typeof(0,[2 4],1)}
This command usescoder.typeof
to specify one variable-size input for functionfoo
. The first argument,0
, indicates the input data type (double
) and complexity (real
). The second argument,[2 4]
, indicates the size, a matrix with two dimensions. The third argument,1
, indicates that the input is variable sized. The upper bound is 2 for the first dimension and 4 for the second dimension.
Note
During compilation,codegen
detects variables and structure fields that change size after you define them, and reports these occurrences as errors. In addition,codegen
performs a run-time check to generate errors when data exceeds upper bounds.
- Fix size mismatch errors:
- Fix upper bounds errors
- Generate C/C++ code using the codegen function.
Generate Code for a MATLAB Function That Expands a Vector in a Loop
- About the MATLAB Function myuniquetol
- Step 1: Add Compilation Directive for Code Generation
- Step 2: Address Issues Detected by the Code Analyzer
- Step 3: Generate MEX Code
- Step 4: Generate C Code
- Step 5: Specify an Upper Bound for the Output Vector
- Step 6: Change the Dynamic Memory Allocation Threshold
About the MATLAB Function myuniquetol
This example uses the function myuniquetol
. This function returns in vector B
a version of input vectorA
, where the elements are unique to within tolerancetol
of each other. In vector B
,abs
(B
(i
) -B
(j
)) > tol
for alli
and j
. Initially, assume input vectorA
can store up to 100 elements.
function B = myuniquetol(A, tol) A = sort(A); B = A(1); k = 1; for i = 2:length(A) if abs(A(k) - A(i)) > tol B = [B A(i)]; k = i; end end
Step 1: Add Compilation Directive for Code Generation
Add the %#codegen
compilation directive at the top of the function:
function B = myuniquetol(A, tol) %#codegen A = sort(A); B = A(1); k = 1; for i = 2:length(A) if abs(A(k) - A(i)) > tol B = [B A(i)]; k = i; end end
Step 2: Address Issues Detected by the Code Analyzer
The Code Analyzer detects that variable B
might change size in the for-
loop. It issues this warning:
The variable 'B' appears to change size on every loop iteration. Consider preallocating for speed.
In this function, you expect vector B
to expand in size because it adds values from vector A
. Therefore, you can ignore this warning.
Step 3: Generate MEX Code
It is a best practice to generate MEX code before you generate C/C++ code. Generating MEX code can identify code generation issues that are harder to detect at run time.
- Generate a MEX function for
myuniquetol
:
codegen -report myuniquetol -args {coder.typeof(0,[1 100],1),coder.typeof(0)}What do these command-line options mean?
The-args
option specifies the class, complexity, and size of each input to functionmyuniquetol
:- The first argument,
coder.typeof
, defines a variable-size input. The expressioncoder.typeof(0,[1 100],1)
defines inputA
as a real double vector with a fixed upper bound. Its first dimension is fixed at 1 and its second dimension can vary in size up to 100 elements.
For more information, see Specify Variable-Size Inputs at the Command Line. - The second argument,
coder.typeof(0)
, defines inputtol
as a real double scalar.
The-report
option instructscodegen
to generate a code generation report, regardless of whether errors or warnings occur.
For more information, see the codegen reference page.
Code generation is successful.codegen
does not detect issues. In the current folder,codegen
generates a MEX function formyuniquetol
and provides a link to the code generation report.
- The first argument,
- Click the View report link.
- In the code generation report, select the Variables tab.
The size ofA
is1x:100
because you specified thatA
is variable size with an upper bound of100
. The size of variableB
is1x:?
, indicating that it is variable size with no upper bounds.
Step 4: Generate C Code
Generate C code for variable-size inputs. By default, codegen
allocates memory statically for data whose size is less than the dynamic memory allocation threshold of 64 kilobytes. If the size of the data is greater than or equal to the threshold or is unbounded, codegen
allocates memory dynamically on the heap.
- Create a configuration option for C library generation:
- Issue this command:
codegen -config cfg -report myuniquetol -args {coder.typeof(0,[1 100],1),coder.typeof(0)}codegen
generates a static library in the default location,codegen\lib\myuniquetol
and provides a link to the code generation report. - Click the View report link.
- In the list of generated files, click
myuniquetol.h
.
The function declaration is:
extern void myuniquetol(const double A_data[], const int A_size[2], double tol,
emxArray_real_T *B);codegen
computes the size ofA
and, because its maximum size is less than the default dynamic memory allocation threshold of 64k bytes, allocates this memory statically. The generated code contains:double A_data[]
: the definition ofA
.int A_size[2]
: the actual size of the input.
The code generator determines thatB
is variable size with unknown upper bounds. It representsB
asemxArray_real_T
. MATLAB provides utility functions for creating and interacting withemxArrays
in your generated code. For more information, see Use C Arrays in the Generated Function Interfaces.
Step 5: Specify an Upper Bound for the Output Vector
You specified that the input A
is variable size with an upper bound of 100
. Therefore, you know that the outputB
cannot be larger than 100
elements.
- Use
coder.varsize
to indicate thatB
is variable size with an upper bound of100
.
function B = myuniquetol(A, tol) %#codegen
A = sort(A);
coder.varsize('B', [1 100], [0 1]);
B = A(1);
k = 1;
for i = 2:length(A)
if abs(A(k) - A(i)) > tol
B = [B A(i)];
k = i;
end
end - Generate code.
codegen -config cfg -report myuniquetol -args {coder.typeof(0,[1 100],1),coder.typeof(0)}
The function declaration is:
extern void myuniquetol(const double A_data[], const int A_size[2], double tol,
double B_data[], int B_size[2]);
The code generator statically allocates the memory forB
. It stores the size ofB
inint B_size[2]
.
Step 6: Change the Dynamic Memory Allocation Threshold
In this step, you reduce the dynamic memory allocation threshold and generate code for an input that exceeds this threshold. This step specifies that the second dimension of A
has an upper bound of10000
.
- Change the upper bound of
B
to match the upper bound ofA
.
function B = myuniquetol(A, tol) %#codegen
A = sort(A);
coder.varsize('B', [1 10000], [0 1]);
B = A(1);
k = 1;
for i = 2:length(A)
if abs(A(k) - A(i)) > tol
B = [B A(i)];
k = i;
end
end - Set the dynamic memory allocation threshold to 4 kilobytes and generate code where the size of input
A
exceeds this threshold.
cfg.DynamicMemoryAllocationThreshold=4096;
codegen -config cfg -report myuniquetol -args {coder.typeof(0,[1 10000],1),coder.typeof(0)} - View the generated code in the report. Because the maximum size of
A
andB
now exceed the dynamic memory allocation threshold,codegen
allocatesA
andB
dynamically on the heap. In the generated code,A
andB
have typeemxArray_real_T
.
extern void myuniquetol(const emxArray_real_T *A, double tol, emxArray_real_T *B);