Интерфейс с основными данными строк в 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, который использует размещение с основной строкой, затем программное обеспечение преобразует входные данные блока в основные строки и выходные данные блока обратно в основной столбец, при необходимости. Преобразования размещения массива могут повлиять на эффективность. Для получения дополнительной информации о соображениях производительности для макета массива, смотрите Code Design для макета Row-Major Array.

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

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

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

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

Основная строка Размещения для N-мерных массивов

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

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

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

Удалите 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-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
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

См. также

| | | |

Похожие темы