exponenta event banner

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

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

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

Задать макет основной строки

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

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

Создать код C для 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

Результатом создания кода является код C:

... 
/* 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. Откройте диалоговое окно «Создание». На странице «Создать код» щелкните стрелку «Создать».

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

  3. На вкладке «Память» задайте формат массива: Row-major.

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

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

Компоновка массива и алгоритмическая эффективность

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

[col + 10 * row]

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

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

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

При создании кода создается код C:

... 
/* 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-цикле. Поэтому основной C-код столбца должен выполнять шаг из 20 элементов для каждого последовательного доступа к памяти.

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

Макет основной строки для N-мерных массивов

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

Рассмотрим функцию-пример addMatrix3D, которая принимает трехмерные входные данные.

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

Генератор кода создает код C:

... 
/* 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-loop выполняет итерацию по смежным элементам, разделенным только одной позицией в памяти. Сравните различия с созданным кодом, использующим формат «основной столбец»:

... 
/* 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-loop теперь выполняет итерацию по смежным элементам, разделенным 200 позициями в памяти. Большая длина шага может привести к снижению производительности из-за пропусков кэш-памяти.

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

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

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

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

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

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

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

См. также

| | | | |

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