Specify Array Layout in Functions and Classes
You can specialize individual MATLAB® functions for row-major layout or column-major layout by inserting
coder.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:
Incrementally modify your code for row-major layout or column-major layout.
Define array layout boundaries for applications that require different layouts in different components.
Structure the inheritance of array layout between many different functions and classes.
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 the
codegen
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:
If you do not specify the array layout in a class constructor, objects inherit their array layout from the function that calls the class constructor, or from code generation configuration settings.
You cannot specify the array layout in a nonstatic method by using
coder.rowMajor
orcoder.columnMajor
. Methods use the same array layout as the receiving object. Methods do not inherit the array layout of the function that calls them. For static methods, which are used similarly to ordinary functions, you can specify the array layout in the method.If you specify the array layout of a superclass, the subclass inherits this array layout specification. You cannot specify conflicting array layouts between superclasses and subclasses.
See Also
coder.columnMajor
| coder.rowMajor
| coder.isRowMajor
| coder.isColumnMajor
| codegen