Сгенерируйте код, который использует n-мерную индексацию

По умолчанию генератор кода использует одномерную индексацию для массивов. Генератор кода создает одномерные массивы в коде C/C++ для N-мерных массивов в коде MATLAB®. Можно использовать N-мерную индексацию, чтобы улучшить удобочитаемость и адаптировать интерфейс к сгенерированному коду.

Эта таблица показывает пример различий в сгенерированном коде с и без N-мерной индексации.

КОД MATLAB

Сгенерированный код C (значение по умолчанию)

Сгенерированный код C с N-D индексация Enabled

A = zeros(2,4,6)
A[48]
  • С размещением главного массива столбца (значение по умолчанию):

    A[6][4][2]
    
  • С включенным размещением главного массива строки:

    A[2][4][6]
    

Порядок индексов инвертируется для N-мерной индексации, потому что MATLAB генерирует код, который использует размещение главного массива столбца по умолчанию. Чтобы переключить порядок индексов, можно включить размещение главного массива строки.

Преобразование N-мерного массива к одной размерности также называется выравниванием массивов. В памяти компьютера все данные хранятся с точки зрения одномерных массивов. Выбор индексации не изменяет результаты вычисления. Однако, если ваш код имеет вводы или выводы, которые являются массивами, интерфейс к вашему сгенерированному коду может измениться.

Включить N-мерную индексацию:

  • Используйте опцию -preservearraydims:

    codegen foo -preservearraydims
  • Установите свойство PreserveArrayDimensions для своего объекта настройки генерации кода к true. Например:

    cfg = coder.config('lib');
    cfg.PreserveArrayDimensions = true;
    codegen foo -config cfg

Включить N-мерную индексацию из MATLAB Coder™App:

  • Перейдите к странице Generate Code в рабочем процессе генерации кода.

  • Откройте диалоговое окно Generate путем нажатия на стрелку Generate.

  • Нажмите More Settings.

  • На вкладке Memory установите флажок Preserve array dimensions.

Улучшите удобочитаемость с n-мерной индексацией и главным строкой размещением

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-мерная индексация

Выбор размещения массивов влияет на внешний вид 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-мерную индексацию.

Смотрите также

| |

Похожие темы