Задайте размещение массива в функциях и классах

Вы можете специализироваться на отдельных MATLAB® функции для размещения основной строки или размещения основной колонны путем вставки coder.rowMajor или coder.columnMajor вызывает в тело функции. Используя эти функциональные специализации, можно объединить основные данные строк и основные данные столбцов в сгенерированном коде. Можно также специализировать классы для одного определенного размещения массива. Функциональные и классовые специализации позволяют вам:

  • Пошагово измените код для размещения основной строки или размещения основной столбца.

  • Задайте контуры размещения массива для приложений, которые требуют различных размещений в различных компонентах.

  • Структурируйте наследование размещения массива между многими различными функциями и классами.

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

Примечание

По умолчанию генерация кода использует размещение массива с основным столбцом.

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

Для примера специализированной функции рассмотрим addMatrixRM:

function [S] = addMatrixRM(A,B) 
%#codegen
S = zeros(size(A));
coder.rowMajor; % specify row-major code
for row = 1:size(A,1) 
   for col = 1:size(A,2)  
       S(row,col) = A(row,col) + B(row,col);
   end
end

Для MATLAB Coder можно сгенерировать код для addMatrixRM при помощи codegen команда.

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

Из-за coder.rowMajor генератор кода создает код, который использует данные, сохраненные в размещении.

Другие функции, вызываемые из функции основной строки или функции основной столбца, наследуют то же размещение массива. Если вызываемая функция имеет свое собственное различие coder.rowMajor или coder.columnMajor вызов, локальный вызов имеет приоритет.

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

Размещение массива запросов функции

Чтобы запросить размещение массива функции во время компиляции, используйте coder.isRowMajor или coder.isColumnMajor. Этот запрос может быть полезен для специализации вашего сгенерированного кода, когда он включает функции основной строки и основной столбца. Для примера рассмотрим эту функцию:

function [S] = addMatrixRouted(A,B)
 if coder.isRowMajor
     %execute this code if row-major
     S = addMatrixRM(A,B); 
 elseif coder.isColumnMajor
     %execute this code if column-major
     S = addMatrix_OptimizedForColumnMajor(A,B);
 end

Эта функция ведет себя по-разному в зависимости от того, является ли она основной строкой или основной столбцом. Когда addMatrixRouted является основной строкой, она вызывает addMatrixRM функция, которая имеет эффективный доступ к памяти для основных данных строк. Когда функция является основной в столбце, она вызывает версию addMatrixRM функция оптимизирована для данных основного столбца.

Для примера рассмотрим это определение функции. Алгоритм итерирует через столбцы во внешнем контуре и строки во внутреннем цикле, в отличие от addMatrixRM функция.

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

Генерация кода для этой функции приводит к:

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

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

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

Можно задать размещение массива для класса, чтобы переменные свойств объектов хранились с определенным размещением массива. Чтобы задать размещение массива, поместите a coder.rowMajor или coder.columnMajor вызов в конструкторе классов. Если вы присваиваете объект с заданным размещением массива свойству другого объекта, размещение массива назначенного объекта имеет приоритет.

Рассмотрим класс с основной строкой rowMats в качестве примера. Этот класс содержит свойства матрицы и метод, который состоит из поэлементного алгоритма сложения. Алгоритм в методе выполняет более эффективно для данных, сохраненных в основном размещении. Путем определения coder.rowMajor в конструкторе классов сгенерированный код использует размещение основной строки для данных свойства.

classdef rowMats
    properties (Access = public)
        A;
        B;
        C;
    end
    methods
        function obj = rowMats(A,B)
            coder.rowMajor;
            if nargin == 0
                obj.A = 0;
                obj.B = 0;
                obj.C = 0;
            else
                obj.A = A;
                obj.B = B;
                obj.C = zeros(size(A));
            end
        end
        function obj = add(obj)
            for row = 1:size(obj.A,1)
                for col = 1:size(obj.A,2)
                    obj.C(row,col) = obj.A(row,col) + obj.B(row,col);
                end
            end
        end
    end
end

Используйте класс в простой функции doMath. Входы и выходы функции точки входа должны все использовать одно и то же размещение массива.

function [out] = doMath(in1,in2)
%#codegen
out = zeros(size(in1));
myMats = rowMats(in1,in2);
myMats = myMats.add;
out = myMats.C;
end

Для MATLAB Coder можно сгенерировать код, введя:

A = rand(20,10);
B = rand(20,10);
cfg = coder.config('lib');
codegen -config cfg doMath -args {A,B} -launchreport

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

При разработке класса для определенного размещения массива примите во внимание:

  • Если вы не задаете размещение массива в конструкторе класса, объекты наследуют своё размещение массива от функции, которая вызывает конструктор класса, или от настроек строения генерации кода.

  • Вы не можете задать размещение массива в нестатическом методе при помощи coder.rowMajor или coder.columnMajor. Методы используют то же размещение массива, что и принимающий объект. Методы не наследуют размещение массива функции, которая вызывает их. Для статических методов, которые используются аналогично обычным функциям, можно задать размещение массива в методе.

  • Если вы задаете размещение массива суперкласса, подкласс наследует эту спецификацию размещения массива. Вы не можете задать конфликтующие размещения массивов между суперклассами и подклассами.

См. также

| | | |

Похожие темы