Hauptinhalt

Code Design for Row-Major Array Layout

Outside of code generation, MATLAB® uses column-major layout by default. Array layout specifications do not affect self-contained MATLAB code. To test the efficiency of your generated code or your MATLAB Function block, create separate versions with row-major layout and column-major layout. Then, compare their performance.

You can design your MATLAB code to avoid potential inefficiencies related to array layout. Inefficiencies can be caused by:

  • Conversions between row-major layout and column-major layout.

  • One-dimensional or linear indexing of row-major data.

  • Reshaping or rearrangement of row-major data.

Array layout conversions are necessary when you mix row-major and column-major specifications in the same code or model, or when you use linear indexing on data that is stored in row-major. When you simulate a model or generate code for a model that uses column-major, and that contains a MATLAB Function block that uses row-major, then the software converts input data to row-major and output data back to column-major as needed, and vice versa.

Inefficiencies can be caused by functions or algorithms that are less optimized for a given choice of array layout. If a function or algorithm is more efficient for a different layout, you can enforce that layout by using coder.rowMajor or coder.columnMajor.

Understand Potential Inefficiencies Caused by Array Layout

This example shows how switching between row-major and column-major layouts can cause inefficiencies in the generated code.

Consider this MATLAB function, which uses coder.ceval to pass data with row-major and column-major layouts.

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 layouts
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

This function uses the external C files addMatrixRM.h, addMatrixRM.c, addMatrixCM.h, and addMatrixCM.c.

 addMatrixRM.h

 addMatrixRM.c

 addMatrixCM.h

 addMatrixCM.c

To instruct the code generator to highlight potential issues to do with array layout, create a code the configuration object and set the property HighlightPotentialRowMajorIssues to true. Generate code that uses row-major layout by using the codegen command with the -rowmajor option.

cfg = coder.config("lib"); 
cfg.HighlightPotentialRowMajorIssues = true; 
codegen -config cfg -launchreport -rowmajor myMixedFn2 -args {ones(20,10),ones(20,10)}

Examine the code generation report. The report displays potential issues to do with array layout on the Code Insights tab, under the Potential row major issues section.

Code generation report for myMixedFn2 showing potential row major issues.

The code generation reports highlights array layout inefficiencies in myMixedFn2 because:

  • The code generator must convert the input variables x and y to column-major layout before passing them to addMatrixCM. In must generate code to transpose these arrays.

  • The code generator must transpose the output variable A back into row-major layout, because myMixedFn2 uses row-major layout.

  • The for-loop uses linear indexing, which requires column-major data. The code generator must recalculate the linear indexing because variables A and B have row-major layouts.

Linear Indexing Uses Column-Major Array Layout

The code generator follows MATLAB column-major semantics for linear indexing. For more information on linear indexing in MATLAB, see Array Indexing.

To use linear indexing on row-major data, the code generator must first recalculate the data representation in column-major layout. This additional processing can slow performance. To improve code efficiency, avoid using linear indexing on row-major data. Alternatively, use column-major layout for code that uses linear indexing.

For example, consider this function, which accepts a matrix as an input and outputs a scalar value. The function uses linear indexing on the input matrix to sum the product of each matrix element with an adjacent element. The output value of this operation depends on the order in which the input elements are stored.

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 the sum
mySum = sum( B.*circshift(B,1) );
end

When you generate code for this function, the code generator must insert a reshaping operation to rearrange the data from row-major layout for A to column-major layout for B. This additional operation reduces the efficiency of the function for row-major layout. The inefficiency increases with the size of the array. Because linear indexing always uses column-major layout, the generated code for sumShiftedProducts produces the same output result whether it is generated with row-major layout or column-major layout.

In general, functions that compute indices or subscripts also use linear indexing, and produce results corresponding to data stored in column-major layout. These functions include:

See Also

| | | |

Topics