exponenta event banner

Принудительное использование генератором кода рекурсии времени выполнения

Когда код 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, по одному для каждого вызова. Специализации можно просмотреть в отчете MATLAB Function.

Для принудительного выполнения рекурсии во время выполнения, в 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

В отчете Функция MATLAB отображается только одна специализация.

Ввод в переменный размер рекурсивной функции

Рассмотрим этот код:

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

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