Принудительный генератор кода для использования рекурсии во время выполнения

Когда ваш MATLAB® код включает рекурсивные вызовы функций, генератор кода использует рекурсию во время компиляции или во время выполнения. С рекурсией во время компиляции генератор кода создает несколько версий рекурсивной функции в сгенерированном коде. Эти версии известны как функциональные специализации. При рекурсии во время выполнения генератор кода производит рекурсивную функцию. Если рекурсия во время компиляции приводит к слишком большому количеству специализаций функций или если вы предпочитаете рекурсию во время выполнения, можно попытаться заставить генератор кода использовать рекурсию во время выполнения. Попробуйте один из следующих подходов:

Обработайте вход в рекурсивную функцию как неконстантный

Рассмотрим эту функцию:

function y = call_recfcn(n)
A = ones(1,n);
x = 5;
y = recfcn(A,x);
end

function y = recfcn(A,x)
if size(A,2) == 1 || x == 1
    y = A(1);
else
    y = A(1)+recfcn(A(2:end),x-1);
end
end

call_recfcn вызовы recfcn со значением 5 для второго аргумента. recfcn вызывает себя рекурсивно до тех пор, пока x равен 1. Для каждого recfcn вызов, входной параметр x имеет другое значение. Генератор кода производит пять специализаций recfcnпо одному для каждого вызова. Со специализациями можно ознакомиться в отчете Функция MATLAB.

Для принудительной рекурсии во время выполнения, в call_recfcn, в вызове на recfcn, дайте команду генератору кода обработать значение входного параметра x как неконстантное значение при помощи coder.ignoreConst.

function y = call_recfcn(n)
A = ones(1,n);
x = coder.ignoreConst(5);
y = recfcn(A,x);
end

function y = recfcn(A,x)
if size(A,2) == 1 || x == 1
    y = A(1);
else
    y = A(1)+recfcn(A(2:end),x-1);
end
end

В отчете Функция MATLAB отображается только одна специализация.

Сделайте вход в переменную рекурсивной функции - размер

Рассмотрим этот код:

function z = call_mysum(A)
%#codegen
z = mysum(A);
end

function y = mysum(A)
coder.inline('never');
if size(A,2) == 1
    y = A(1);
else
    y = A(1)+ mysum(A(2:end));
end
end

Если вход в mysum является фиксированным размером, генератор кода использует рекурсию во время компиляции. Чтобы заставить генератор кода использовать преобразование во время выполнения, сделайте вход mysum переменный размер при помощи coder.varsize.

function z = call_mysum(A)
%#codegen
B = A;
coder.varsize('B');
z = mysum(B);
end

function y = mysum(A)
coder.inline('never');
if size(A,2) == 1
    y = A(1);
else
    y = A(1)+ mysum(A(2:end));
end
end

Назначение выходной переменной перед рекурсивным вызовом

Генератор кода использует рекурсию во время компиляции для этого кода:

function y = callrecursive(n)
x = 10;
y = myrecursive(x,n);
end

function y = myrecursive(x,n)
coder.inline('never')
if x > 1
    y = n + myrecursive(x-1,n-1);
    
else
    y = n;
end
end

Чтобы заставить генератор кода использовать рекурсию во время выполнения, измените myrecursive так, чтобы выход y назначается перед рекурсивным вызовом. Поместите назначение y = n в if блок и рекурсивный вызов в else блок.

function y = callrecursive(n)
x = 10;
y = myrecursive(x,n);
end

function y = myrecursive(x,n)
coder.inline('never')
if x == 1
    y = n;  
else
    y = n + myrecursive(x-1,n-1);
end
end

Похожие темы