Подтвердить что ты не робот

Как генерация кода MATLAB выводит размер вывода с вложенными ветвями

При генерации кода C с использованием MATLAB Coder поведение отличается, когда if происходит в теле другого if или в разделе else. Следующий случай легко создает C-код с выходом размером 5x5:

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

Теперь это тоже работает

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

Но этот не сгенерирует код, жалуясь на несоответствие размера:

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

Вот результат в командной строке:

>> 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)

Я видел это поведение в MATLAB R2013b и R2015a.

4b9b3361

Ответ 1

Из документы, Matlab codegen должен знать размер матрицы во время компиляции, если codegen не указано или не указано, что матрица имеет переменный размер. Существует несколько способов дать Matlab знать, что матрица будет иметь переменный размер:

  • Используя функцию coder.varsize, можно явно объявить матрицу переменной величины.
  • 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

Почему Matlab хочет знать эту информацию? Если размер матрицы известен во время компиляции, возможны всевозможные дополнительные оптимизации (цикл разворачивания и т.д.).

Ответ 2

Я согласен с ответом Мэтью Ганна, это должно добавить некоторое объяснение для поведения. Хорошая ментальная модель для того, чтобы узнать, как Coder анализирует ваш код MATLAB, так это то, что он смотрит на него сверху вниз.

Применяя эту ментальную модель, в ваших первых двух примерах назначения, определяющие размеры y: y = zeros(2,2) и y = zeros(5,5), происходят до того, как значение y когда-либо используется. Таким образом, Coder может объединить оба размера, чтобы автоматически сделать y массив с переменным размером. В третьем примере выполняется назначение y = zeros(2,2), а затем используется y: y = 2 * y. На этом этапе Coder должен определить размер и тип умножения 2 * y. Отображается только назначение 2-by-2, поэтому предполагается, что 2 * y также должен возвращать матрицу 2-by-2.

Выполнение этого вывода затем включает в себя предположение, что y 2-by-2 в коде и по существу блокирует размер y, так что последующее присвоение y с матрицей 5-by-5 должно завершиться неудачей.