По умолчанию генератор кода использует одномерную индексацию для массивов. Генератор кода создает одномерные массивы в коде C/C + + для N-мерных массивов в MATLAB® код. Вы можете использовать N-мерную индексацию, чтобы улучшить читаемость и адаптировать интерфейс к своему сгенерированному коду.
В этой таблице показан пример различий в сгенерированном коде с N-мерной индексацией и без нее.
Код MATLAB | Сгенерированный код C (по умолчанию) | Сгенерированный код C с включенной индексацией N-D |
---|---|---|
A = zeros(2,4,6) |
A[48] |
|
Порядок индексов сторнируется для N-мерного индексирования, потому что MATLAB генерирует код, который по умолчанию использует размещение массива с основным столбцом. Чтобы переключить порядок индексов, можно включить размещение массива с основной строкой.
Преобразование N-мерного массива в одну размерность также называется уплощением массива. В памяти компьютера все данные хранятся в терминах одномерных массивов. Выбор индексации не меняет результаты расчетов. Однако, если ваш код имеет входы или выходы, которые являются массивами, интерфейс с вашим сгенерированным кодом может измениться.
Чтобы включить N-мерную индексацию:
Используйте -preservearraydims
опция:
codegen foo -preservearraydims
Установите PreserveArrayDimensions
свойство для объекта строения генерации кода, чтобы true
. Для примера:
cfg = coder.config('lib'); cfg.PreserveArrayDimensions = true; codegen foo -config cfg
Чтобы включить N-мерную индексацию из приложения MATLAB Coder™:
Перейдите на страницу Generate Code в рабочем процессе генерации кода.
Откройте диалоговое окно Generate, щелкнув стрелу Generate.
Нажмите More Settings.
На вкладке Memory установите флажок Preserve array dimensions.
N-мерная индексация может упростить для вас отслеживание вашего сгенерированного кода C/C + + назад к коду MATLAB. Генератор кода сохраняет размерности исходных массивов, а не преобразует массивы в одно измерение. Кроме того, можно задать основную строку размещения, чтобы сделать внешний вид кода еще более интуитивно понятным.
Рассмотрим функцию MATLAB addMatrices
, который добавляет две матрицы, элемент за элементом:
function sum = addMatrices(A,B) %#codegen sum = coder.nullcopy(A); for row = 1:size(A,1) for col = 1:size(A,2) sum(row,col) = A(row,col) + B(row,col); end end
Сгенерируйте код для addMatrices
так, что он работает с массивами 2 на 4. Включите N-мерную индексацию и размещение массива с основной строкой:
cfg = coder.config('lib'); cfg.PreserveArrayDimensions = true; cfg.RowMajor = true; codegen addMatrices -args {ones(2,4),ones(2,4)} -config cfg -launchreport
Генерация кода создает код с явной двумерной индексацией массива:
/* N-d indexing on, row-major on */ void addMatrices(double A[2][4], double B[2][4], double sum[2][4]) { int row; int col; for (row = 0; row < 2; row++) { for (col = 0; col < 4; col++) { sum[row][col] = A[row][col] + B[row][col]; } } }
Сгенерированный код для addMatrices
использует ту же двумерную индексацию, что и оригинальный код MATLAB. Можно легко проанализировать сгенерированный код по сравнению с исходным алгоритмом. Чтобы понять, как использовать размещение основной строки, см. Раздел «Генерация кода, который использует размещение массива основной строки».
Выбор размещения массива влияет на внешний вид N-мерного индексирования. Для примера сгенерируйте код для addMatrices
функция с использованием размещения массива основного столбца:
cfg.RowMajor = false; codegen addMatrices -args {ones(2,4),ones(2,4)} -config cfg -launchreport
Генерация кода создает этот код C:
/* N-d indexing on, row-major off */ void addMatrices(double A[4][2], double B[4][2], double sum[4][2]) { int row; int col; for (row = 0; row < 2; row++) { for (col = 0; col < 4; col++) { sum[col][row] = A[col][row] + B[col][row]; } } }
Входная и выходные матрицы в коде С являются транспонированием исходных матриц MATLAB. Чтобы понять, почему, рассмотрим, как массивы представлены в памяти компьютера. Язык MATLAB по умолчанию использует размещение с основным столбцом, где элементы первого (крайнего левого) размерности или индекса смежны в памяти. По умолчанию C использует размещение массива с основной строкой, где элементы последнего (крайнего правого) размерности или индекса смежны. Чтобы сохранить смежность исходного элемента, генератор кода должен изменить порядок измерений массива.
Например, в этом случае, если вы задаете матрицу MATLAB A
как:
A=reshape(1:8,2,4)
или
A = 1 3 5 7 2 4 6 8
затем, поскольку MATLAB использует размещение основного столбца, данные внутренне хранятся в следующем порядке:
A(:)' = 1 2 3 4 5 6 7 8
В коде С необходимо транспонировать исходные данные, в данном примере вызвать его AA
:
AA = {{1, 2}, {3, 4}, {5, 6}, {7, 8}};
для получения списка элементов данных с тем же внутренним порядком на хранение. Другими словами, массив C должен быть 4 на 2. (Можно получить эквивалентный порядок на хранение, определив массив как 2 на 4, с AA = {{1, 2, 3, 4}, {5, 6, 7, 8}}
. Однако получение этого порядка требует ручного изменения формы или перестройки данных.)
Выбор размещения массива влияет только на представление внутренних данных и не изменяет вычислительные или алгоритмические результаты. Чтобы сохранить интуитивно понятный внешний вид массивов MATLAB в сгенерированном коде, используйте N-мерную индексацию с размещением массива с основной строкой. Обратите внимание, что основные размещения могут повлиять на эффективность вашего сгенерированного кода. Для получения дополнительной информации смотрите Проект для Row-Major Array Layout.
Рассмотрим другие аспекты N-мерного индексирования. Генератор кода всегда производит одномерные массивы для N-мерных векторов, даже когда вы задаете N-мерную индексацию. Для примера, если вы генерируете код для вектора MATLAB:
A = zeros(1,10)
или
A = zeros(1,10,1)
получившиеся массивы C/C + + сохраняются как:
A[10]
N-мерная индексация также применяется к массивам и структурам. Для примера, если вы декларируете структуры в своем коде как:
x = struct('f1', ones(2,3)); coder.cstructname(x,'myStruct1'); y = struct('f2', ones(1,6,1)); coder.cstructname(y,'myStruct2');
затем сгенерированный код содержит определения структур:
typedef struct { double f1[2][3]; } myStruct1; typedef struct { double f2[6]; } myStruct2;
Избегайте линейной индексации на N-мерных массивах. Линейная индексация происходит, например, когда вы используете оператор двоеточия:
A(:)
Чтобы применить линейную индексацию, генератор кода должен привести N-мерный массив в одномерный массив. Операции кастинга делают ваш код более комплексным для генератора кода, чтобы анализировать. Эта повышенная сложность может затруднить способность генератора кода оптимизировать для эффективности.
Наконец, обратите внимание на следующее:
Вы можете использовать N-мерную индексацию для массивов любого типа данных.
N-размерную индексацию могут использовать только массивы фиксированного размера, а не массивы переменного размера.
codegen
| coder.cstructname
| reshape