Вне генерации кода, MATLAB® по умолчанию используется размещение основного столбца. Спецификации размещения массива не влияют на автономный код MATLAB. Чтобы проверить эффективность вашего сгенерированного кода или блока MATLAB Function, создайте отдельные версии с размещением строки и основным размещением столбца. Затем сравните их эффективность.
Можно спроектировать код MATLAB, чтобы избежать потенциальных неэффективностей, связанных с размещением массива. Неэффективность может быть вызвана:
Преобразования между размещением основной строки и размещением основной колонны.
Одномерная или линейная индексация данных основной строки.
Изменение формы или перестройка данных основной строки.
Преобразования размещения массива необходимы, когда вы смешиваете основные и основные спецификации столбцов в том же коде или модели, или когда вы используете линейную индексацию данных, которая хранится в основных строках. Когда вы симулируете модель или генерируете код для модели, которая использует основной столбец, и которая содержит блок MATLAB Function, который использует большую строку, тогда программное обеспечение преобразует входные данные в основные и выходные данные обратно в основной столбец, при необходимости, и наоборот.
Неэффективности могут быть вызваны функциями или алгоритмами, которые менее оптимизированы для заданного выбора размещения массива. Если функция или алгоритм более эффективны для другого размещения, можно применить это размещение, встраивая его в другую функцию с coder.rowMajor
или coder.columnMajor
вызов.
Рассмотрим код для myMixedFn2
, который использует coder.ceval
для передачи данных с основной строкой и основным размещением столбца:
function [B, C] = myMixedFn2(x,y) %#codegen % specify type of return arguments for ceval calls A = zeros(size(x)); B = zeros(size(x)); C = 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 column-major order coder.ceval('-layout:columnMajor','addMatrixCM', ... coder.rref(x),coder.rref(y),coder.wref(A)); % compute B for i = 1:numel(A) B(i) = A(i) + 7; end % call C function that uses row-major order coder.ceval('-layout:rowMajor','addMatrixRM', ... coder.rref(y),coder.rref(B),coder.wref(C)); end
Внешние файлы:
Объявите объект строения, cfg
. Сгенерируйте код, который использует размещение основной строки при помощи -rowmajor
опция.
cfg = coder.config('lib'); cfg.HighlightPotentialRowMajorIssues = true; codegen myMixedFn2 -args {ones(20,10),ones(20,10)} -config cfg -launchreport -rowmajor
Выделенные проблемы отображаются в отчете генерации кода, на вкладке Code Insights, под разделом Potential row major issues.
Неэффективность размещения массива возникает здесь из-за:
Генератор кода должен преобразовать входные переменные x
и y
в размещение основной колонки перед их передачей в addMatrixCM
. Транспозиции должны быть вставлены в сгенерированный код.
Генератор кода должен транспонировать переменный выход A
назад в основную строку размещения, потому что myMixedFn2
использует размещение основной строки.
Цикл for использует линейную индексацию, которая требует данных основной столбец. Генератор кода должен пересчитать линейную индексацию, потому что переменные A
и B
хранятся в основной строке.
Генератор кода следует основной семантике MATLAB для линейной индексации. Дополнительные сведения о линейной индексации в MATLAB см. в разделе Индексация массивов.
Чтобы использовать линейную индексацию для данных основной строки, генератор кода должен сначала пересчитать представление данных в размещении основной столбца. Эта дополнительная обработка может снизить эффективность. Чтобы улучшить эффективность кода, избегайте использования линейной индексации данных основной строки или используйте размещение основной столбца для кода, который использует линейную индексацию.
Для примера рассмотрим функцию sumShiftedProducts
, который принимает матрицу как вход и выводит скалярное значение. Функция использует линейную индексацию на матрице входа, чтобы суммировать продукт каждого элемента матрицы с соседним элементом. Выходное значение этой операции зависит от порядка хранения входных элементов.
function mySum = sumShiftedProducts(A) %#codegen mySum = 0; % create linear vector of A elements B = A(:); % multiply B by B with elements shifted by one, and take sum mySum = sum( B.*circshift(B,1) ); end
Для MATLAB Coder™, чтобы сгенерировать код, который использует размещение основной строки, введите:
codegen -config:mex sumShiftedProducts -args {ones(2,3)} -launchreport -rowmajor
Для примера входа рассмотрим матрицу:
D = reshape(1:6,3,2)'
который приводит к:
D = 1 2 3 4 5 6
Если вы передаете эту матрицу как вход в сгенерированный код, элементы A
хранятся в порядке:
1 2 3 4 5 6
Напротив, потому что вектор B
получается линейным индексированием, хранится в порядке:
1 4 2 5 3 6
Генератор кода должен вставить операцию изменения формы, чтобы переставить данные из размещения основной строки для A
к размещению основного столбца для B
. Эта дополнительная операция снижает эффективность функции для размещения основной строки. Неэффективность увеличивается с размером массива. Поскольку линейная индексация всегда использует размещение с основным столбцом, сгенерированный код для sumShiftedProducts
приводит к тому же выход результату, сгенерированному с помощью основного размещения строки или основного размещения столбца.
В целом функции, которые вычисляют индексы или нижние индексы, также используют линейное индексирование и дают результаты, соответствующие данным, хранящимся в размещении столбца. Эти функции включают:
coder.ceval
| coder.columnMajor
| coder.isColumnMajor
| coder.isRowMajor
| coder.rowMajor