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

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

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

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

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

Для функций точки входа все вводы и выводы должны использовать то же размещение массивов. Генератор кода принимает, что входные параметры функции точки входа и выходные параметры хранятся с тем же размещением массивов как функция.

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

Для примера специализированной функции рассмотрите 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

Сгенерируйте код для 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

Сгенерируйте код при помощи этого скрипта:

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

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

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

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

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

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

| | | |

Похожие темы