Размещение массивов может быть важно для интегрирования, удобства пользования и эффективности. Генератор кода производит код, который использует упорядоченное по столбцам размещение по умолчанию. Однако много устройств, датчиков и библиотек используют упорядоченное по строкам размещение массивов для своих данных. Можно применить код непосредственно к этим данным путем генерации кода, который использует упорядоченное по строкам размещение. Размещение массивов может также влиять на эффективность. Много алгоритмов выполняют доступ к памяти более эффективно для одного определенного размещения массивов.
Можно задать упорядоченное по строкам размещение массивов в командной строке со свойствами настройки генерации кода, или при помощи приложения 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
параметр в объекте настройки генерации кода. Можно использовать этот параметр с любым типом объекта настройки: 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
. Чтобы интегрировать эту функцию в ваш код, вызовите функцию с помощью '-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
Внешние файлы:
Сгенерировать код, введите:
codegen -config:lib myMixedFn1 -args {ones(20,10),ones(20,10)} -rowmajor -launchreport
codegen
| coder.ceval
| coder.columnMajor
| coder.isColumnMajor
| coder.isRowMajor
| coder.rowMajor