По умолчанию генератор кода использует одномерную индексацию для массивов. Генератор кода создает одномерные массивы в коде C/C++ для N-мерных массивов в коде MATLAB®. Можно использовать N-мерную индексацию, чтобы улучшить удобочитаемость и адаптировать интерфейс к сгенерированному коду.
Эта таблица показывает пример различий в сгенерированном коде с и без N-мерной индексации.
КОД MATLAB | Сгенерированный код C (значение по умолчанию) | Сгенерированный код C с N-D индексация Enabled |
---|---|---|
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
Генерация кода производит этот код С:
/* 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-мерную индексацию с упорядоченным по строкам размещением массивов. Обратите внимание на то, что упорядоченное по строкам размещение может влиять на КПД вашего сгенерированного кода. Для получения дополнительной информации см. Проект Кода для Упорядоченного по строкам Размещения Массивов.
Рассмотрите другие аспекты 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