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