Сгенерируйте код, который использует упорядоченное по строкам размещение массивов

Размещение массивов может быть важно для интегрирования, удобства пользования и производительности. Генератор кода производит код, который использует упорядоченное по столбцам размещение по умолчанию. Однако много устройств, датчиков и библиотек используют упорядоченное по строкам размещение массивов в своих данных. Можно применить код непосредственно к этим данным путем генерации кода, который использует упорядоченное по строкам размещение. Размещение массивов может также влиять на производительность. Много алгоритмов выполняют доступ к памяти более эффективно для одного определенного размещения массивов.

Можно задать упорядоченное по строкам размещение массивов в командной строке со свойствами настройки генерации кода, или при помощи приложения MATLAB® Coder™. Можно также задать упорядоченное по строкам размещение или упорядоченное по столбцам размещение для отдельных функций и классов. Вводы и выводы вашей точки входа функции (верхнего уровня) должны все использовать то же размещение массивов.

Задайте упорядоченное по строкам размещение

Рассмотрите эту функцию для добавления двух матриц. Алгоритм выполняет сложение через явный обход строки и столбца.

function [S] = addMatrix(A,B) 
%#codegen
S = zeros(size(A));
for row = 1:size(A,1) 
   for col = 1:size(A,2)  
       S(row,col) = A(row,col) + B(row,col);
   end
end

Сгенерируйте код С для addMatrix при помощи -rowmajor опция. Задайте форму входных параметров при помощи -args опция и запуск отчет генерации кода.

codegen addMatrix -args {ones(20,10),ones(20,10)} -config:lib -launchreport -rowmajor

В качестве альтернативы сконфигурируйте свой код для упорядоченного по строкам размещения путем изменения RowMajor параметр в объекте настройки генерации кода. Можно использовать этот параметр с любым типом объекта настройки: libMEX, dll, или exe.

cfg = coder.config('lib'); 
cfg.RowMajor = true; 
codegen addMatrix -args {ones(20,10),ones(20,10)} -config cfg -launchreport

Генерация кода приводит к этому коду С:

... 
/* generated code for addMatrix using row-major */
for (row = 0; row < 20; row++) { 
  for (col = 0; col < 10; col++) {
      S[col + 10 * row] = A[col + 10 * row] + B[col + 10 * row];   
   }
} 
...

Задавать упорядоченное по строкам размещение с приложением MATLAB Coder:

  1. Откройте диалоговое окно Generate. На странице Generate Code кликните по стреле Generate.

  2. Нажмите More Settings.

  3. На вкладке Memory, набор Array layout: Row-major.

Чтобы проверить, что ваш сгенерированный код использует упорядоченное по строкам размещение, сравните индексацию массива в своем сгенерированном коде с индексацией массива в коде, который использует упорядоченное по столбцам размещение. Можно также сгенерировать код, который использует N-мерную индексацию. N-мерная индексация может иметь значения в более очевидном размещении массивов. Для получения дополнительной информации смотрите, Генерируют Код, Который Использует N-мерную Индексацию.

MATLAB хранит данные в упорядоченном по столбцам размещении по умолчанию. Когда вы вызываете сгенерированную MEX-функцию, которая использует упорядоченное по строкам размещение, программное обеспечение автоматически преобразует входные данные от упорядоченного по столбцам размещения до упорядоченного по строкам размещения. Выходные данные, возвращенные в MEX-функцию, преобразованы назад в упорядоченное по столбцам размещение. Для автономного lib, dll, и exe генерация кода, генератор кода принимает, что входные параметры функции точки входа и выходные параметры хранятся с тем же размещением массивов как функция.

Размещение массивов и алгоритмический КПД

Для определенных алгоритмов упорядоченное по строкам размещение обеспечивает более эффективный доступ к памяти. Считайте код С показанным для addMatrix это использует упорядоченное по строкам размещение. Массивы индексируются сгенерированным кодом с помощью формулы:

[col + 10 * row]

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

Используя упорядоченное по столбцам размещение для данных приводит к более долгой длине шага и менее эффективному доступу к памяти. Чтобы видеть это сравнение, сгенерируйте код, который использует упорядоченное по столбцам размещение:

codegen addMatrix -args {ones(20,10),ones(20,10)} -config:lib -launchreport

Генерация кода производит этот код С:

... 
/* generated code for addMatrix using column-major */
for (row = 0; row < 20; row++) {
  for (col = 0; col < 10; col++) {
     S[row + 20 * col] = A[row + 20 * col] + B[row + 20 * col];  
  }
}
...

В упорядоченном по столбцам размещении элементы столбца непрерывны в памяти в сгенерированном коде. Смежные элементы памяти разделяются шагом одной строки и индексируются формулой:

[row + 20 * col]

Однако алгоритм выполняет итерации через столбцы во внутреннем цикле for. Поэтому упорядоченный по столбцам код С должен сделать шаг 20 элементов для каждого последовательного доступа к памяти.

Размещение массивов, которое обеспечивает самый эффективный доступ к памяти, зависит от алгоритма. Для этого алгоритма упорядоченное по строкам размещение данных обеспечивает более эффективный доступ к памяти. Алгоритм пересекает по строке данных строкой. Упорядоченное по строкам устройство хранения данных поэтому более эффективно.

Упорядоченное по строкам размещение для n-мерных массивов

Можно использовать упорядоченное по строкам размещение в N-мерных массивах. Когда массив хранится в упорядоченном по строкам размещении, элементы от последней (самой правой) размерности или индекса непрерывны в памяти. В упорядоченном по столбцам размещении элементы от первой (крайней левой) размерности или индекса непрерывны.

Считайте функцию, взятую в качестве примера, addMatrix3D, который принимает 3D входные параметры.

function [S] = addMatrix3D(A,B)
%#codegen
S = zeros(size(A));
for i = 1:size(A,1)
    for j = 1:size(A,2)
        for k = 1:size(A,3)
            S(i,j,k) = A(i,j,k) + B(i,j,k);
        end
    end
end
end

Сгенерируйте код, который использует упорядоченное по строкам размещение:

codegen addMatrix3D -args {ones(20,10,5),ones(20,10,5)} -config:lib -launchreport -rowmajor

Генератор кода производит этот код С:

... 
/* row-major layout */
for (i = 0; i < 20; i++) {
    for (j = 0; j < 10; j++) {
        for (k = 0; k < 5; k++) {
            S[(k + 5 * j) + 50 * i] = A[(k + 5 * j) + 50 * i] 
                                      + B[(k + 5 * j) + 50 * i];
        }
    }
}
...

В упорядоченном по строкам размещении смежные элементы памяти разделяются одним шагом последнего индекса, k. Внутренний цикл for выполняет итерации по смежным элементам, разделенным только одним положением в памяти. Сравните различия для сгенерированного кода, который использует упорядоченное по столбцам размещение:

... 
/* column-major layout */
for (i = 0; i < 20; i++) {
    for (j = 0; j < 10; j++) {
        for (k = 0; k < 5; k++) {
            S[(i + 20 * j) + 200 * k] = A[(i + 20 * j) + 200 * k]
                                        + B[(i + 20 * j) + 200 * k];
        }
    }
}
...

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

Поскольку алгоритм выполняет итерации через последний индекс, k, во внутреннем цикле for длина шага намного более долга для сгенерированного кода, который использует упорядоченное по столбцам размещение. Для этого алгоритма упорядоченное по строкам размещение данных обеспечивает более эффективный доступ к памяти.

Задайте размещение массивов во внешних вызовах функции

Чтобы вызвать внешние функции C/C++ что ожидаемые данные, сохраненные определенным размещением, используйте coder.ceval с layout синтаксис. Если вы не используете этот синтаксис, внешние входные параметры функции и выходные параметры приняты, чтобы использовать упорядоченное по столбцам размещение по умолчанию.

Считайте внешнюю функцию C спроектированной, чтобы использовать упорядоченное по строкам размещение под названием myCFunctionRM. Чтобы интегрировать эту функцию в ваш код, вызовите функцию с помощью '-layout:rowMajor' или '-row' опция. Эта опция гарантирует, что массивы ввода и вывода хранятся в упорядоченном по строкам порядке. Генератор кода автоматически вставляет преобразования размещения массивов по мере необходимости.

coder.ceval('-layout:rowMajor','myCFunctionRM',coder.ref(in),coder.ref(out)) 

В функции MATLAB, которая использует упорядоченное по строкам размещение, можно стремиться вызвать внешнюю функцию, спроектированную, чтобы использовать упорядоченное по столбцам размещение. В этом случае используйте '-layout:columnMajor' или '-col' опция.

coder.ceval('-layout:columnMajor','myCFunctionCM',coder.ref(in),coder.ref(out)) 

Можно выполнить упорядоченные по строкам и упорядоченные по столбцам вызовы функции в том же коде. Рассмотрите функциональный myMixedFn1 как пример:

function [E] = myMixedFn1(x,y)
%#codegen
% specify type of return arguments for ceval calls
D = zeros(size(x)); 
E = zeros(size(x));

% include external C functions that use row-major & column-major
coder.cinclude('addMatrixRM.h'); 
coder.updateBuildInfo('addSourceFiles', 'addMatrixRM.c');
coder.cinclude('addMatrixCM.h'); 
coder.updateBuildInfo('addSourceFiles', 'addMatrixCM.c');

% call C function that uses row-major order
coder.ceval('-layout:rowMajor','addMatrixRM', ...
    coder.rref(x),coder.rref(y),coder.wref(D));

% call C function that uses column-major order
coder.ceval('-layout:columnMajor','addMatrixCM', ...
    coder.rref(x),coder.rref(D),coder.wref(E));
end

Внешние файлы:

 addMatrixRM.h

 addMatrixRM.c

 addMatrixCM.h

 addMatrixCM.c

Сгенерировать код, введите:

codegen -config:lib myMixedFn1 -args {ones(20,10),ones(20,10)} -rowmajor -launchreport

Смотрите также

| | | | |

Похожие темы