По умолчанию генератор кода использует одномерное индексирование для массивов. Генератор кода создает одномерные массивы в коде 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), щелкнув стрелку Создать (Generate).![]()
Щелкните Дополнительные параметры.
На вкладке «Память» установите флажок «Сохранить размеры массива».
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];
}
}
}Входные и выходные матрицы в коде C представляют собой транспозиции исходных матриц 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В коде C необходимо транспонировать исходные данные, например, вызвать их. 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-мерную индексацию с макетом основного массива строк. Обратите внимание, что макет основной строки может повлиять на эффективность созданного кода. Дополнительные сведения см. в разделе Разработка кода для макета основного массива строк.
Рассмотрим другие аспекты 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