Specify Array Layout in Functions and Classes - MATLAB & Simulink (original) (raw)

You can specialize individual MATLAB® functions for row-major layout or column-major layout by insertingcoder.rowMajor or coder.columnMajor calls into the function body. Using these function specializations, you can combine row-major data and column-major data in your generated code. You can also specialize classes for one specific array layout. Function and class specializations allow you to:

For MATLAB Coderâ„¢ entry-point (top-level) functions, all inputs and outputs must use the same array layout. In the generated C/C++ code, the entry-point function interface accepts and returns data with the same array layout as the function array layout specification.

Note

By default, code generation uses column-major array layout.

Specify Array Layout in a Function

For an example of a specialized function, consider 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

For MATLAB Coder, you can generate code for addMatrixRM by using thecodegen command.

codegen addMatrixRM -args {ones(20,10),ones(20,10)} -config:lib -launchreport

Because of the coder.rowMajor call, the code generator produces code that uses data stored in row-major layout.

Other functions called from a row-major function or column-major function inherit the same array layout. If a called function has its own distinct coder.rowMajor or coder.columnMajor call, the local call takes precedence.

You can mix column-major and row-major functions in the same code. The code generator inserts transpose or conversion operations when passing data between row-major and column-major functions. These conversion operations ensure that array elements are stored as required by functions with different array layout specifications. For example, the inputs to a column-major function, called from a row-major function, are converted to column-major layout before being passed to the column-major function.

Query Array Layout of a Function

To query the array layout of a function at compile time, use coder.isRowMajor or coder.isColumnMajor. This query can be useful for specializing your generated code when it involves row-major and column-major functions. For example, consider this function:

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

This function behaves differently depending on whether it is row-major or column-major. When addMatrixRouted is row-major, it calls the addMatrixRM function, which has efficient memory access for row-major data. When the function is column-major, it calls a version of the addMatrixRM function optimized for column-major data.

For example, consider this function definition. The algorithm iterates through the columns in the outer loop and the rows in the inner loop, in contrast to the addMatrixRM function.

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

Code generation for this function yields:

... /* 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];
} } ...

The generated code has a stride length of only one element. Due to the specializing queries, the generated code for addMatrixRouted provides efficient memory access for either choice of array layout.

Specify Array Layout in a Class

You can specify array layout for a class so that object property variables are stored with a specific array layout. To specify the array layout, place a coder.rowMajor or coder.columnMajor call in the class constructor. If you assign an object with a specified array layout to the property of another object, the array layout of the assigned object takes precedence.

Consider the row-major class rowMats as an example. This class contains matrix properties and a method that consists of an element-wise addition algorithm. The algorithm in the method performs more efficiently for data stored in row-major layout. By specifying coder.rowMajor in the class constructor, the generated code uses row-major layout for the property data.

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

Use the class in a simple function doMath. The inputs and outputs of the entry-point function must all use the same array layout.

function [out] = doMath(in1,in2) %#codegen out = zeros(size(in1)); myMats = rowMats(in1,in2); myMats = myMats.add; out = myMats.C; end

For MATLAB Coder, you can generate code by entering:

A = rand(20,10); B = rand(20,10); cfg = coder.config('lib'); codegen -config cfg doMath -args {A,B} -launchreport

With default settings, the code generator assumes that the entry-point function inputs and outputs use column-major layout, because you do not specify row-major layout for the function doMath. Therefore, before calling the class constructor, the generated code converts in1 and in2 to row-major layout. Similarly, it converts the doMath function output back to column-major layout.

When designing a class for a specific array layout, consider:

See Also

coder.columnMajor | coder.rowMajor | coder.isRowMajor | coder.isColumnMajor | codegen