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

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

Похожие темы