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