Разблокируйте for- Циклы

Когда генератор кода разворачивает for-цикл, вместо создания for-loop в сгенерированном коде, он создает копию тела цикла для каждой итерации. Для небольших плотных циклов размотка может улучшить эффективность. Однако для больших циклов развертывание может значительно увеличить время генерации кода и сгенерировать неэффективный код.

Цикл силы при помощи coder.unroll

Генератор кода использует эвристику, чтобы определить, когда развернуть for-цикл. Чтобы принудительно разворачивать цикл, используйте coder.unroll. Это влияет только на for цикл, который сразу после coder.unroll. Для примера:

function z = call_myloop()
%#codegen
z = myloop(5);
end

function b = myloop(n)
b = zeros(1,n);
coder.unroll();
for i = 1:n
    b(i)=i+n;
end
end

Вот сгенерированный код для for-loop:

  z[0] = 6.0;
  z[1] = 7.0;
  z[2] = 8.0;
  z[3] = 9.0;
  z[4] = 10.0;

Для управления, когда a for-цикл разворачивается, используйте coder.unroll flag аргумент. Для примера разверните цикл только, когда количество итераций меньше 10.

function z = call_myloop()
%#codegen
z = myloop(5);
end

function b = myloop(n)
unroll_flag = n < 10;
b = zeros(1,n);
coder.unroll(unroll_flag);
for i = 1:n
    b(i)=i+n;
end
end

Чтобы развернуть for-цикл, генератор кода должен быть в состоянии определять границы for-цикл. Для примера генерация кода прекращается для следующего кода, потому что значение n не известно во время генерации кода.

function b = myloop(n)
b = zeros(1,n);
coder.unroll();
for i = 1:n
    b(i)=i+n;
end
end

Установите порог размотки цикла для всех for-Циклы в коде MATLAB

Если for-цикл не предшествует coder.unrollгенератор кода использует циклический порог разворачивания, чтобы определить, следует ли автоматически разворачивать цикл. Если количество итераций цикла меньше порога, генератор кода разворачивает цикл. Если количество итераций больше или равно порогу, генератор кода производит for-цикл. Пороговое значение по умолчанию 5. Изменяя этот порог, можно точно настроить размотку цикла. Чтобы изменить порог:

  • В объекте строения для автономной генерации кода (coder.CodeConfig или coder.EmbeddedCodeConfig), установите LoopUnrollThreshold свойство.

  • В MATLAB® Coder™ приложение, на вкладке Speed, установите Loop unrolling threshold.

В отличие от coder.unroll директива, порог применяется ко всем for-циклы в коде MATLAB. Порог может также применяться к некоторым for- циклы, произведенные во время генерации кода.

Для отдельного цикла, a coder.unroll директива имеет приоритет над циклом развертывания оптимизации.

Развертывание простых for- Циклы

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

function [x,y] = call_myloops()
%#codegen
x = myloop1(5);
y = myloop2(5);
end

function b = myloop1(n)
b = zeros(1,n);
for i = 1:n
    b(i)=i+n;
end
end

function b = myloop2(n)
b = zeros(1,n);
for i = 1:n
    b(i)=i*n;
end
end

Чтобы задать значение порога разворачивания цикла равным 6, а затем сгенерируйте статическую библиотеку, запустите:

cfg = coder.CodeConfig;
cfg.LoopUnrollThreshold = 6;
codegen call_myloops -config cfg

Это сгенерированный код для for-циклы. Генератор кода развернул оба for-циклы.

  x[0] = 6.0;
  y[0] = 5.0;
  x[1] = 7.0;
  y[1] = 10.0;
  x[2] = 8.0;
  y[2] = 15.0;
  x[3] = 9.0;
  y[3] = 20.0;
  x[4] = 10.0;
  y[4] = 25.0;

Удаление вложенных for- Циклы

Предположим, что ваш код MATLAB имеет два вложенных for-циклы.

  • Если количество итераций внутреннего цикла меньше порога, генератор кода сначала разворачивает внутренний цикл. Впоследствии, если продукт количества итераций двух циклов также меньше порога, генератор кода разворачивает внешний контур. В противном случае генератор кода производит внешнюю for-цикл.

  • Если количество итераций внутреннего цикла равно или больше порога, генератор кода производит обе for-циклы.

Это поведение обобщено на несколько вложенных for-циклы.

Рассмотрим функцию nestedloops_1 с двумя вложенными for-циклы:

function y = nestedloops_1
%#codegen
y = zeros(2,2);
for i = 1:2
    for j = 1:2
        y(i,j) = i+j;
    end
end
end

Сгенерируйте код для nestedloops_1 с циклом разворачивающимся порогом, установленным на значение по умолчанию 5. Вот сгенерированный код для for-циклы. Генератор кода развернул обе for-loops, потому что продукт количества итераций двух циклов 4, что меньше порога.

  y[0] = 2.0;
  y[2] = 3.0;
  y[1] = 3.0;
  y[3] = 4.0;

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

function y = nestedloops_2
%#codegen
y = zeros(3,2);
for i = 1:3
    for j = 1:2
        y(i,j) = i+j;
    end
end
end

Количество итераций внутреннего цикла меньше порога. Генератор кода разворачивает внутренний цикл. Но продукт количества итераций двух циклов 6, что больше порога. Поэтому генератор кода производит код для внешнего for-цикл. Вот сгенерированный код для for-циклы.

  for (i = 0; i < 3; i++) {
    y[i] = (double)i + 2.0;
    y[i + 3] = ((double)i + 1.0) + 2.0;
  }

См. также

Похожие темы