Contenuto principale

Specify Upper Bounds for Variable-Size Arrays in Generated Code

During code generation, the code generator attempts to calculate the upper bounds of the arrays in the MATLAB® code. When the code generator is unable to identify an upper bound, it designates an array dimension as unbounded. The code generator must dynamically allocate memory for arrays with unbounded dimensions, which can lead to the slower execution of the generated code. You can prevent the code generator from designating an input array as unbounded by specifying explicit upper bounds at code generation time. You can also set explicit upper bounds in the MATLAB code by using assert statements or the coder.varsize directive.

The code generator is unable to determine an upper bound for an array dimension when the size of the array depends on a value that is not a constant during code generation. For example:

  • You specify the size of array by using a run-time value.

  • You grow an array in a loop, and the number of loop iterations depends on a run-time value.

  • You construct an array by using an array construction function, such as ones or zeros, and use one of the size argument variables in a nested function.

To see the upper bounds of arrays in the generated code, inspect the code generation report. See Code Generation Reports.

Specify Upper Bounds at Code Generation Time

If the size of an array dimension in the generated code depends on the size of an entry-point input argument, you can specify upper bounds for the argument at code generation time by using one of these approaches:

For example, consider this MATLAB function:

function out = varSizeInput(n) %#codegen
out = n;
end

If you generate code for varSizeInput at the command line, you can use coder.typeof to specify the upper bounds of n. For example, this command specifies that n is a matrix of doubles with two variable-size dimensions. The upper bound for the first dimension is 3 and the upper bound for the second dimension is 100.

codegen -report varSizeInput -args {coder.typeof(0,[3 100],[true true])}
You can use the code generation report to verify the size of n in the generated code.

Code generation report, showing the size of n

Specify Upper Bounds Explicitly by Using coder.varsize

To specify the upper bound of an array dimension directly in your MATLAB code, use coder.varsize. When you specify an upper bound for a variable by using coder.varsize, the upper bound becomes part of the type specification for that variable. The type specification persists even through complicated code paths.

For example, this function uses coder.varsize to specify that the second dimension of Y is variable size and has an upper bound of 10.

function out = constrainVarsize(u) %#codegen
Y = [1 2 3 4 5];
coder.varsize('Y',[1 10],[false true]);
if (u > 0)
    Y = [Y Y+u];
else
    Y = [Y Y*u];
end
out = Y;
end
If you generate code for constrainVarsize, the code generation report shows that the second dimension of Y is variable size and has an upper bound of 10.

Code generation report, showing the size of Y

Specify Upper Bounds Indirectly by Using assert Statements

If the upper bounds of an array in the MATLAB code depends on a value that is not a constant at code generation time, you can constrain the value of the variable by using the assert function. When you use an assert statement to constrain a value that specifies an upper bound, this specification helps the code generator to determine upper bounds, but the upper bound does not become part of the type definition.

For example, this function uses an input value to construct an array. It uses an assert statement to restrict the input value to less than or equal to 5.

function out = constrainAssert(n) %#codegen
assert (n <= 5);
out = ones(n,n);
end

If you generate code for constrainAssert, the code generation report shows that both dimensions of out are variable size and have an upper bound of 5.

Code generation report, showing the size of out

You can also use an assert statement to specify the upper bounds of an array dimension when the MATLAB code calculates the array size based on input variables. For example, this function uses an assert statement to constrain the value of size.

function out = constrainMultAssert(n,m) %#codegen
size = n*m;
assert (size <= 25);
out = ones(1,size);
end

If you generate code for constrainMultAssert, the code generation report shows that the second dimension of out is variable size and has an upper bound of 25.

Code generation report, showing the size of out

Choose Whether to Specify Upper Bounds Directly or Indirectly

Because the upper bounds that you specify for a variable by using coder.varsize become part of the type definition, these upper bounds can persist over complicated code paths. When you specify upper bounds indirectly by using assert statements, the upper bounds are not part of the type definition. Instead, the code generator uses the information in the assert statement during code generation when it calculates upper bounds. When you use an assert statement to constrain the number of loop iterations, the code generator is unable to deduce the upper bounds of an array that you grow inside the loop. In addition, if you use an assert statement to constrain the size of a variable that you use in a nested function and then use this variable as a size argument to an array-construction function, the code generator cannot deduce the upper bounds for the constructed array from the assert statement. In these situations, use coder.varsize to directly specify upper bounds.

Specify Upper Bounds When Growing Arrays in Loops

If an array is inside of a loop and the number of loop iterations is a run-time value, you cannot specify the upper bounds of the array by constraining the number of loop iterations using an assert statement. Instead, use coder.varsize to explicitly specify the upper bounds of the array.

For example, consider this function, which uses end+1 to grow the second dimension of n in a for-loop.

function out = restrictLoopAssert(n) %#codegen
out = 0;
assert(n <= 5) 
for i = 1:n
    out(end+1) = i;
end
end

If you generate code for restrictLoopAssert, the code generation report shows that the second dimension of out is unbounded. Even though the assert statement restricts the number of loop iterations to a maximum of 5, the code generator is unable to recognize that the second dimension of out has an upper bound of 6.

Code generation report, showing the size of out

To explicitly specify the upper bounds of out, use coder.varsize. For example:

function out = restrictLoopVarsize(n) %#codegen
out = 0;
coder.varsize("out",[1 6],[false true])
for i = 1:n
    out(end+1) = i;
end
end

If you generate code for restrictLoopAssert, the code generation report shows that the second dimension of out is variable size with an upper bound of 6.

Code generation report, showing the size of out

Specify Upper Bounds for Variables in Nested Functions

If the MATLAB code uses a variable inside of a nested function and then uses the same variable to construct an array, you cannot set upper bounds for the array by using an assert to constrain the size of the variable.

For example, consider this function, which uses the variable innerVar in the nested function nestedFun and restricts the size of this variable by using an assert statement. After the assert statement, the function specifies the size of the second dimension of out by using the variable innerVar.

function out = restrictNestedAssert(n)
    function x = nestedFun
        if innerVar <= 50
            x = 42;
        else
            x = 22;
        end
    end
innerVar = n;
assert(innerVar <= 100);
x = nestedFun;
out = ones(x,innerVar);
end

If you generate code for restrictNestedAssert, the code generation report shows that the second dimension of out is unbounded. Even though the assert statement restricts the value of innerVar to 100 or less, the code generator is unable to apply this restriction because innerVar is used in the nested function nestedFun.

Code generation report, showing the size of out

To explicitly specify the upper bounds of out, use coder.varsize.

For example:

function out = restrictNestedVarsize(n) %#codegen
    function x = nestedFun
        if innerVar <= 50
            x = 42;
        else
            x = 22;
        end
    end
innerVar = n;
coder.varsize("out",[42 100],[true true])
x = nestedFun;
out = ones(x,innerVar);
end

If you generate code for restrictNestedVarsize, the code generation report shows that the second dimension of out is variable size with an upper bound of 100.

Code generation report, showing the size of out

Alternatively, apply the assert statement to a temporary variable that you do not use in the nested function. For example, if you generate code for this function, the code generation reports shows that out has a size of :42x:100.

function out = restrictNonNested(n) %#codegen
    function x = nestedFun
        if innerVar <= 50
            x = 42;
        else
            x = 22;
        end
    end
innerVar = n;
temp = innerVar;
assert(temp <= 100);
x = nestedFun;
out = ones(x,temp);
end

See Also

Apps

Blocks

Functions

Topics