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

Проблема

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

Compile-time recursion limit reached. Size or type of
input #1 of function 'foo' may change at every call.
Compile-time recursion limit reached. Size 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.

Чтобы увеличить предел, в ускоряющем объекте настройки кода, увеличивают значение параметра конфигурации CompileTimeRecursionLimit.

Похожие темы