Вы видите сообщение, такое как:
Compile-time recursion limit reached. Size or type of input #1 of function 'foo' may change at every call.
Compile-time recursion limit reached. Value of input #1 of function 'foo' may change at every call.
С рекурсией времени компиляции генератор кода производит несколько версий рекурсивной функции вместо того, чтобы произвести рекурсивную функцию в сгенерированном коде. Эти версии известны как функциональные специализации. Генератор кода не может использовать рекурсию времени компиляции для рекурсивной функции в вашем коде MATLAB®, потому что количество функциональных специализаций превышает предел.
Чтобы решить проблему, попробуйте одно из этих решений:
Для этого сообщения:
Compile-time recursion limit reached. Value of input #1 of function 'foo' may change at every call.
Используйте это решение:
Обеспечьте рекурсию во время выполнения путем обработки входного значения как непостоянного.
Для этого сообщения:
Compile-time recursion limit reached. Size or type of input #1 of function 'foo' may change at every call.
В отчете генерации кода посмотрите на функциональные специализации. Если вы видите, что размер аргумента изменяется для каждой функциональной специализации, то попробуйте это решение:
Обеспечьте рекурсию во время выполнения путем создания размера входной переменной.
Рассмотрите эту функцию:
function y = call_recfcn(n) A = ones(1,n); x = 100; 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
Второй вход к recfcn
имеет постоянное значение 100. Генератор кода решает, что количество рекурсивных вызовов конечно и пытается произвести 100 копий recfcn
. Это количество специализаций превышает предел рекурсии времени компиляции. Чтобы обеспечить рекурсию во время выполнения, дайте генератору кода команду обрабатывать второй вход как непостоянное значение при помощи coder.ignoreConst
.
function y = call_recfcn(n) A = ones(1,n); x = coder.ignoreConst(100); 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
фиксированный размер, генератор кода использует рекурсию времени компиляции. Если A
является достаточно большим, количество функциональных специализаций превышает предел времени компиляции. Чтобы заставить генератор кода использовать преобразование во время выполнения, сделайте вход к 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
Предел рекурсии времени компиляции по умолчанию 50 является достаточно большим для большинства рекурсивных функций, которые требуют рекурсии времени компиляции. Обычно, увеличение предела не устраняет проблему. Однако, если можно определить количество рекурсивных вызовов, и вы хотите рекурсию времени компиляции, увеличиваете предел. Например, рассмотрите эту функцию:
function z = call_mysum() %#codegen B = 1:125; 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
Можно решить, что генератор кода производит 125 копий mysum
функция. В этом случае, если вы хотите рекурсию времени компиляции, увеличиваете предел рекурсии времени компиляции 125.
Чтобы увеличить предел, в ускоряющем объекте настройки кода, увеличивают значение CompileTimeRecursionLimit
параметр конфигурации.