Обеспечьте генератор кода, чтобы использовать рекурсию во время выполнения

Когда ваш код 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

Похожие темы