Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How MATLAB code generation infers output size with nested branches

When generating C code using MATLAB Coder, the behaviour is different when an if happens in body of another if or in its elsesection. The following case easily creates C code with output having size 5x5:

function y = foo1(u)
if u > 0
    y = zeros(2,2);
else
    y = zeros(5,5);
end

Now this one works as well

function y = foo2(u,v)
if u > 0
    y = zeros(2,2);
else
    y = zeros(5,5);
    if v > 0
        y = 2 * y;
    end
end

But this one fails to generate code, complaining about size mismatch:

function y = foo3(u,v)
if u > 0
    y = zeros(2,2);
    if v > 0
        y = 2 * y;
    end
else
    y = zeros(5,5);
end

Here is the output in command-line:

>> codegen foo1.m -args {0}
>> codegen foo2.m -args {0,0}
>> codegen foo3.m -args {0,0}
??? Size mismatch (size [2 x 2] ~= size [5 x 5]).
The size to the left is the size of the left-hand side of the assignment.

Error in ==> foo3 Line: 8 Column: 5
Code generation failed: Open error report.
Error using codegen (line 144)

I have seen this behaviour in MATLAB R2013b and R2015a.

like image 782
Mohsen Nosratinia Avatar asked Nov 26 '15 13:11

Mohsen Nosratinia


1 Answers

From the docs, Matlab codegen must know the size of a matrix at compile time unless codegen is told or infers that the matrix is of variable size. There are several ways to let Matlab know a matrix will be of variable size:

  1. Using coder.varsize function, a matrix can be explicitly declared to be of variable size.
  2. MATLAB can infer a matrix is of variable size from the structure of the code.

As your code suggests, option (2) apparently isn't robust. Matlab tries to infer in some cases when there's a simple if else statement, but that inference appears to be quite fragile, as shown by your example.

Rather than rely on MATLAB to correctly infer whether a matrix is variable size, a solution is to make an explicit declaration:

function y = foo3(u,v)
  coder.varsize('y', []);  % Let codegen know y is variable sized 
                           % and can be arbitrary dimensions
                           % an alternative is: coder.varsize('y',[5,5]);
  if u > 0
     y = zeros(2,2);
     if v > 0
       y = 2 * y;
     end
   else
     y = zeros(5,5);
   end

Why might Matlab want to know this information? If a matrix's size is known at compile time, all kinds of additional optimizations may be possible (loop unrolling etc...).

like image 184
Matthew Gunn Avatar answered Oct 04 '22 20:10

Matthew Gunn