exponenta event banner

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

Проблема

Появится следующее сообщение:

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 для функций MATLAB.

Связанные темы