Когда ваш код 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
, один для каждого вызова. После того, как вы сгенерируете код, вы видите специализации в отчете генерации кода.
Чтобы обеспечить рекурсию во время выполнения, в 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
После того, как вы генерируете код в отчете генерации кода., вы видите только одну специализацию.
Рассмотрите этот код:
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