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

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

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

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

Чтобы запросить размещение массивов функции во время компиляции, используйте 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 обеспечивает эффективный доступ к памяти для любого выбора размещения массивов.

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

Можно задать размещение массивов для класса так, чтобы переменные свойства объекта хранились с определенным размещением массивов. Чтобы задать размещение массивов, поместите 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. Методы используют то же размещение массивов в качестве принимающего объекта. Методы не наследовали размещение массивов функции, которая вызывает их. Для статических методов, которые используются так же к обычным функциям, можно задать размещение массивов в методе.

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

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

| | |

Похожие темы