exponenta event banner

Создать код, использующий N-мерное индексирование

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

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

Код MATLAB

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

Сгенерированный код C с включенной индексацией N-D

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™:

  • Перейдите на страницу Создать код в рабочем процессе создания кода.

  • Откройте диалоговое окно Создать (Generate), щелкнув стрелку Создать (Generate).

  • Щелкните Дополнительные параметры.

  • На вкладке «Память» установите флажок «Сохранить размеры массива».

Улучшение читаемости с помощью 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

При создании кода создается код 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-мерную индексацию могут только массивы фиксированного размера, а не массивы переменного размера.

См. также

| |

Связанные темы