Достигнут предел рекурсии во время компиляции

Проблема

Вы видите сообщение, такое как:

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® код, поскольку количество специализаций функций превышает предел.

Решения

Чтобы решить проблему, попробуйте одно из следующих решений:

Рекурсия во время выполнения силы

Рекурсия во время прогона силы путем обработки Входа значения как неконстантного

Рассмотрим эту функцию:

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.

Чтобы увеличить предел, увеличьте значение параметра конфигурации Compile-time recursion limit for MATLAB functions.

Похожие темы