MATLAB代码生成如何使用嵌套分支推断输出大小

Moh*_*nia 11 matlab code-generation matlab-coder

当使用MATLAB Coder生成C代码时,当if在另一个if或其else部分的主体中发生时,行为是不同的.以下情况很容易创建输出大小为5x5的C代码:

function y = foo1(u)
if u > 0
    y = zeros(2,2);
else
    y = zeros(5,5);
end
Run Code Online (Sandbox Code Playgroud)

现在这个也适用

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
Run Code Online (Sandbox Code Playgroud)

但是这个无法生成代码,抱怨大小不匹配:

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
Run Code Online (Sandbox Code Playgroud)

这是命令行中的输出:

>> 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)
Run Code Online (Sandbox Code Playgroud)

我在MATLAB R2013b和R2015a中看到过这种行为.

Mat*_*unn 7

文档中,Matlab codegen必须在编译时知道矩阵的大小,除非 codegen被告知或推断矩阵的大小可变.有几种方法可以让Matlab知道矩阵的大小可变:

  1. 使用coder.varsize函数,可以显式声明矩阵具有可变大小.
  2. MATLAB可以根据代码的结构推断出矩阵的大小可变.

正如您的代码所暗示的那样,选项(2)显然并不健全.在某些情况下,Matlab会尝试推断出一个简单的if else语句,但这种推断似乎非常脆弱,如您的示例所示.

而不是依靠MATLAB来正确地推断矩阵是否是可变大小,解决方案是做出明确的声明:

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
Run Code Online (Sandbox Code Playgroud)

为什么Matlab想知道这些信息?如果在编译时已知矩阵的大小,则可能进行各种额外的优化(循环展开等...).

  • 值得注意的是,没有任何的例子在OP是内部的声明,如果声明将在C.一个单独的范围,因为这些代码在Matlab一个工作的人能希望MATLAB编码器将能够解决这个问题的有效C.变量,但人们不能假设这一点.我想这个问题在`foo3`必须做与`y`在语句中使用(`Y = 2*y`),然后在else语句,这是在文后写的重新定义.我认为这会混淆Matlab编码器.我不完全确定. (2认同)