for
- Циклы и parfor
- ЦиклыКогда генератор кода разворачивает a for
- цикл или parfor
- цикл, вместо того, чтобы произвести цикл в сгенерированном коде, это производит копию тела цикла для каждой итерации. Для маленьких, жестких циклов разворачивание может улучшать производительность. Однако для больших циклов, разворачивание может значительно увеличить время генерации кода и сгенерировать неэффективный код.
for
- Развертывание цикла при помощи coder.unroll
Генератор кода использует эвристику, чтобы определить, когда развернуть a 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:
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
Разворачивать a for
- цикл, генератор кода должен смочь определить границы for
- цикл. Например, генерация кода перестала работать для следующего кода потому что значение n
не известен во время генерации кода.
function b = myloop(n) b = zeros(1,n); coder.unroll(); for i = 1:n b(i)=i+n; end end
for
- Циклы и parfor
- Циклы в коде MATLABЕсли a for
- циклом не предшествуют coder.unroll
, генератор кода использует порог развертывания цикла, чтобы определить, развернуть ли автоматически цикл. Если количество итераций цикла меньше порога, генератор кода разворачивает цикл. Если количество итераций больше или равно порогу, генератор кода производит for
- цикл. При помощи порога развертывания цикла можно также развернуть parfor
- циклы.
Значением по умолчанию порога является 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
- циклы, потому что продуктом количества итераций этих двух циклов является 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; }
parfor
- ЦиклыРассмотрите эту функцию MATLAB:
function [x,y] = parallel_loops() %#codegen x = myloop1(5); y = myloop2(6); end function b = myloop1(n) b = zeros(1,n); parfor (i = 1:n) b(i)=i+n; end end function b = myloop2(n) b = zeros(1,n); parfor (i = 1:n) b(i)=i*n; end end
cfg = coder.CodeConfig; cfg.LoopUnrollThreshold = 6; codegen parallel_loops -config cfg
static void myloop1(double b[5]) { b[0] = 6.0; b[1] = 7.0; b[2] = 8.0; b[3] = 9.0; b[4] = 10.0; } static void myloop2(double b[6]) { int i; #pragma omp parallel for num_threads(omp_get_max_threads()) for (i = 0; i < 6; i++) { b[i] = ((double)i + 1.0) * 6.0; }} void parallel_loops(double x[5], double y[6]) { if (!isInitialized_parallel_loops) { parallel_loops_initialize(); } myloop1(x); myloop2(y);}
Генератор кода развернул только parfor
- цикл, который имеет пять итераций, который меньше порогового значения.