Размещение массивов может быть важно для интегрирования, удобства пользования и производительности. Генератор кода производит код, который использует главное столбцом размещение по умолчанию. Однако много устройств, датчиков и библиотек используют размещение главного массива строки для своих данных. Можно применить код непосредственно к этим данным путем генерации кода, который использует главное строкой размещение. Размещение массивов может также влиять на производительность. Много алгоритмов выполняют доступ к памяти более эффективно для одного определенного размещения массивов.
Можно задать размещение главного массива строки в командной строке со свойствами настройки генерации кода, или при помощи MATLAB® Coder™app. Можно также задать главное строкой размещение или главное столбцом размещение для отдельных функций и классов. Вводы и выводы вашей точки входа функции (верхнего уровня) должны все использовать то же размещение массивов.
Рассмотрите эту функцию для добавления двух матриц. Алгоритм выполняет сложение через явный обход строки и столбца.
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
в объекте настройки генерации кода. Можно использовать этот параметр с любым типом объекта настройки: lib
, mex
, 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:
Откройте диалоговое окно Generate. На странице Generate Code кликните по стрелке Generate.
Нажмите More Settings.
На вкладке 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-мерных массивов. Когда массив хранится в главном строкой размещении, элементы от последней (самой правой) размерности или индекса непрерывны в памяти. В главном столбцом размещении элементы от первой (крайней левой) размерности или индекса непрерывны.
Считайте функцию, взятую в качестве примера, 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
. Чтобы интегрировать эту функцию в ваш код, вызовите функцию с помощью опции '-row'
или '-layout:rowMajor'
. Эта опция гарантирует, что массивы ввода и вывода хранятся в главном строкой порядке. Генератор кода автоматически вставляет преобразования размещения массивов по мере необходимости.
coder.ceval('-layout:rowMajor','myCFunctionRM',coder.ref(in),coder.ref(out))
В функции MATLAB, которая использует главное строкой размещение, можно стремиться вызвать внешнюю функцию, разработанную, чтобы использовать главное столбцом размещение. В этом случае используйте опция '-col'
или '-layout:columnMajor'
.
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
Внешние файлы:
Сгенерировать код, введите:
codegen -config:lib myMixedFn1 -args {ones(20,10),ones(20,10)} -rowmajor -launchreport
codegen
| coder.ceval
| coder.columnMajor
| coder.isColumnMajor
| coder.isRowMajor
| coder.rowMajor