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

Размещение массивов может быть важно для интегрирования, удобства пользования и производительности. Генератор кода производит код, который использует главное столбцом размещение по умолчанию. Однако много устройств, датчиков и библиотек используют размещение главного массива строки для своих данных. Можно применить код непосредственно к этим данным путем генерации кода, который использует главное строкой размещение. Размещение массивов может также влиять на производительность. Много алгоритмов выполняют доступ к памяти более эффективно для одного определенного размещения массивов.

Можно задать размещение главного массива строки в командной строке со свойствами настройки генерации кода, или при помощи MATLAB® Coder™app. Можно также задать главное строкой размещение или главное столбцом размещение для отдельных функций и классов. Вводы и выводы вашей точки входа функции (верхнего уровня) должны все использовать то же размещение массивов.

Задайте главное строкой размещение

Рассмотрите эту функцию для добавления двух матриц. Алгоритм выполняет сложение через явный обход строки и столбца.

function [S] = addMatrix(A,B) 
%#codegen
S = zeros(size(A));
for row = 1:size(A,1) 
   for col = 1:size(A,2)  
       S(row,col) = A(row,col) + B(row,col);
   end
end

Сгенерируйте код С для addMatrix при помощи опции -rowmajor. Задайте форму входных параметров при помощи опции -args и запустите отчет генерации кода.

codegen addMatrix -args {ones(20,10),ones(20,10)} -config:lib -launchreport -rowmajor

Также сконфигурируйте свой код для главного строкой размещения путем изменения параметра RowMajor в объекте настройки генерации кода. Можно использовать этот параметр с любым типом объекта настройки: lib, mex, dll или exe.

cfg = coder.config('lib'); 
cfg.RowMajor = true; 
codegen addMatrix -args {ones(20,10),ones(20,10)} -config cfg -launchreport

Генерация кода приводит к этому коду С:

... 
/* generated code for addMatrix using row-major */
for (row = 0; row < 20; row++) { 
  for (col = 0; col < 10; col++) {
      S[col + 10 * row] = A[col + 10 * row] + B[col + 10 * row];   
   }
} 
...

Задавать главное строкой размещение с приложением MATLAB Coder:

  1. Откройте диалоговое окно Generate. На странице Generate Code кликните по стрелке Generate.

  2. Нажмите More Settings.

  3. На вкладке Memory, набор Array layout: Row-major.

Чтобы проверить, что ваш сгенерированный код использует главное строкой размещение, сравните индексацию массива в своем сгенерированном коде с индексацией массива в коде, который использует главное столбцом размещение. Можно также сгенерировать код, который использует N-мерную индексацию. N-мерная индексация может иметь значения в более очевидном размещении массивов. Для получения дополнительной информации смотрите, Генерируют Код, Который Использует N-мерную Индексацию.

MATLAB хранит данные в главном столбцом размещении по умолчанию. Когда вы вызываете сгенерированную MEX-функцию, которая использует главное строкой размещение, программное обеспечение автоматически преобразовывает входные данные от главного столбцом размещения до главного строкой размещения. Выходные данные, возвращенные в MEX-функцию, преобразованы назад в главное столбцом размещение. Для автономного lib, dll и генерации кода exe, генератор кода принимает, что входные параметры функции точки входа и выходные параметры хранятся с тем же размещением массивов как функция.

Размещение массивов и алгоритмическая эффективность

Для определенных алгоритмов главное строкой размещение обеспечивает более эффективный доступ к памяти. Считайте код С показанным для addMatrix, который использует главное строкой размещение. Массивы индексируются сгенерированным кодом с помощью формулы:

[col + 10 * row]

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

Используя главное столбцом размещение для данных приводит к более долгой длине шага и менее эффективному доступу к памяти. Чтобы видеть это сравнение, сгенерируйте код, который использует главное столбцом размещение:

codegen addMatrix -args {ones(20,10),ones(20,10)} -config:lib -launchreport

Генерация кода производит этот код С:

... 
/* generated code for addMatrix using column-major */
for (row = 0; row < 20; row++) {
  for (col = 0; col < 10; col++) {
     S[row + 20 * col] = A[row + 20 * col] + B[row + 20 * col];  
  }
}
...

В главном столбцом размещении элементы столбца непрерывны в памяти в сгенерированном коде. Смежные элементы памяти разделяются шагом одной строки и индексируются формулой:

[row + 20 * col]

Однако алгоритм выполняет итерации через столбцы во внутреннем цикле for. Поэтому главный столбцом код С должен сделать шаг 20 элементов для каждого последовательного доступа к памяти.

Размещение массивов, которое обеспечивает самый эффективный доступ к памяти, зависит от алгоритма. Для этого алгоритма главное строкой размещение данных обеспечивает более эффективный доступ к памяти. Алгоритм пересекает по строке данных строкой. Главное строкой устройство хранения данных поэтому более эффективно.

Главное строкой размещение для n-мерных массивов

Можно использовать главное строкой размещение для N-мерных массивов. Когда массив хранится в главном строкой размещении, элементы от последней (самой правой) размерности или индекса непрерывны в памяти. В главном столбцом размещении элементы от первой (крайней левой) размерности или индекса непрерывны.

Считайте функцию, взятую в качестве примера, addMatrix3D, который принимает 3D входные параметры.

function [S] = addMatrix3D(A,B)
%#codegen
S = zeros(size(A));
for i = 1:size(A,1)
    for j = 1:size(A,2)
        for k = 1:size(A,3)
            S(i,j,k) = A(i,j,k) + B(i,j,k);
        end
    end
end
end

Сгенерируйте код, который использует главное строкой размещение:

codegen addMatrix3D -args {ones(20,10,5),ones(20,10,5)} -config:lib -launchreport -rowmajor

Генератор кода производит этот код С:

... 
/* row-major layout */
for (i = 0; i < 20; i++) {
    for (j = 0; j < 10; j++) {
        for (k = 0; k < 5; k++) {
            S[(k + 5 * j) + 50 * i] = A[(k + 5 * j) + 50 * i] 
                                      + B[(k + 5 * j) + 50 * i];
        }
    }
}
...

В главном строкой размещении смежные элементы памяти разделяются одним шагом последнего индекса, k. Внутренний цикл for выполняет итерации по смежным элементам, разделенным только одним положением в памяти. Сравните различия для сгенерированного кода, который использует главное столбцом размещение:

... 
/* column-major layout */
for (i = 0; i < 20; i++) {
    for (j = 0; j < 10; j++) {
        for (k = 0; k < 5; k++) {
            S[(i + 20 * j) + 200 * k] = A[(i + 20 * j) + 200 * k]
                                        + B[(i + 20 * j) + 200 * k];
        }
    }
}
...

В главном столбцом размещении смежные элементы разделяются одним шагом первого индекса, i. Внутренний цикл for теперь выполняет итерации по смежным элементам, разделенным 200 положениями в памяти. Долгая длина шага может вызвать ухудшение производительности из-за неудачных обращений в кэш.

Поскольку алгоритм выполняет итерации через последний индекс, k, во внутреннем цикле for, длина шага намного более долга для сгенерированного кода, который использует главное столбцом размещение. Для этого алгоритма главное строкой размещение данных обеспечивает более эффективный доступ к памяти.

Задайте размещение массивов во внешних вызовах функции

Чтобы вызвать внешние функции C/C++ что ожидаемые данные, сохраненные определенным размещением, используйте coder.ceval с синтаксисом layout. Если вы не используете этот синтаксис, внешние входные параметры функции и выходные параметры приняты, чтобы использовать главное столбцом размещение по умолчанию.

Считайте внешнюю функцию C разработанной, чтобы использовать главное строкой размещение под названием myCFunctionRM. Чтобы интегрировать эту функцию в ваш код, вызовите функцию с помощью опции '-row' или '-layout:rowMajor'. Эта опция гарантирует, что массивы ввода и вывода хранятся в главном строкой порядке. Генератор кода автоматически вставляет преобразования размещения массивов по мере необходимости.

coder.ceval('-layout:rowMajor','myCFunctionRM',coder.ref(in),coder.ref(out)) 

В функции MATLAB, которая использует главное строкой размещение, можно стремиться вызвать внешнюю функцию, разработанную, чтобы использовать главное столбцом размещение. В этом случае используйте опция '-col' или '-layout:columnMajor'.

coder.ceval('-layout:columnMajor','myCFunctionCM',coder.ref(in),coder.ref(out)) 

Можно выполнить главные строкой и главные столбцом вызовы функции в том же коде. Рассмотрите функциональный myMixedFn1 как пример:

function [E] = myMixedFn1(x,y)
%#codegen
% specify type of return arguments for ceval calls
D = zeros(size(x)); 
E = zeros(size(x));

% include external C functions that use row-major & column-major
coder.cinclude('addMatrixRM.h'); 
coder.updateBuildInfo('addSourceFiles', 'addMatrixRM.c');
coder.cinclude('addMatrixCM.h'); 
coder.updateBuildInfo('addSourceFiles', 'addMatrixCM.c');

% call C function that uses row-major order
coder.ceval('-layout:rowMajor','addMatrixRM', ...
    coder.rref(x),coder.rref(y),coder.wref(D));

% call C function that uses column-major order
coder.ceval('-layout:columnMajor','addMatrixCM', ...
    coder.rref(x),coder.rref(D),coder.wref(E));
end

Внешние файлы:

 addMatrixRM.h

 addMatrixRM.c

 addMatrixCM.h

 addMatrixCM.c

Сгенерировать код, введите:

codegen -config:lib myMixedFn1 -args {ones(20,10),ones(20,10)} -rowmajor -launchreport

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

| | | | |

Похожие темы