Интерфейс с упорядоченными по строкам данными в блоке MATLAB Function

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

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

Упорядоченное по строкам размещение в симуляции и генерации кода

Для блока MATLAB Function можно задать упорядоченное по строкам размещение массивов в блоке. Эта спецификация происходит на функциональном уровне и не изменяет размещение массивов модели за пределами функции. Размещение массивов, которое вы задаете в блоке MATLAB Function, применяется и к симуляции и к генерации кода C/C++. Смотрите Задают Размещение Массивов в Функциях и Классах.

Для генерации кода C/C++, использующей Simulink Coder™ и программное обеспечение Embedded Coder®, можно задать размещение массивов на уровне модели, который поддерживается блоками MATLAB Function. Для получения дополнительной информации о размещении контролирующего массива на уровне модели смотрите Генерацию кода Матриц и Массивов (Simulink Coder). Установка генерации типового кодекса для размещения массивов не имеет никаких, влияют для симуляции. Смотрите размещение Массивов (Simulink Coder). Для примеров использования упорядоченного по строкам размещения в блоке MATLAB Function для генерации кода смотрите, Генерируют Упорядоченный по строкам Код для Модели, Которая Содержит блок MATLAB function (Simulink Coder).

Для блока MATLAB Function спецификация размещения массивов на функциональном уровне более приоритетна по сравнению со спецификацией размещения массивов модели. Однако для глобальных и персистентных переменных, спецификация размещения массивов модели более приоритетна.

Преобразования размещения массивов

MATLAB® и Simulink хранят данные в упорядоченном по столбцам размещении по умолчанию. Программное обеспечение автоматически вставляет преобразования размещения массивов по мере необходимости, когда вы задаете различные размещения массивов в различных функциях и на различных контурах.

Например, когда вы симулируете модель или генерируете код для модели, которая использует упорядоченное по столбцам размещение, и модель содержит блок MATLAB Function, который использует упорядоченное по строкам размещение, затем программное обеспечение преобразует входные данные блока в упорядоченный по строкам и выходные данные блока назад к упорядоченному по столбцам по мере необходимости. Преобразования размещения массивов могут влиять на эффективность. Для получения дополнительной информации о факторах эффективности для размещения массивов см. Проект Кода для Упорядоченного по строкам Размещения Массивов.

Размещение массивов и алгоритмический КПД

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

function [S] = addMatrix(A,B) 
coder.rowMajor;
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

Если вы используете этот код в блоке MATLAB Function, генерация кода приводит к этому коду С для функции:

... 
/* 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];   
   }
} 
...

Массивы индексируются сгенерированным кодом с помощью формулы:

[col + 10 * row]

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

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

... 
/* 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)
coder.rowMajor;
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

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

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

Удалите coder.rowMajor вызовите и сгенерируйте код С, который использует упорядоченное по столбцам размещение:

... 
/* 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. Чтобы интегрировать эту функцию в ваш код, вызовите функцию с помощью '-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
coder.rowMajor; 
% 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

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

| | | |

Похожие темы