行优先数组布局的代码设计
在代码生成期间外,MATLAB® 默认使用列优先布局。数组布局设定不影响自包含的 MATLAB 代码。要测试您生成的代码或 MATLAB Function 模块的效率,请使用行优先布局和列优先布局创建单独的版本。然后,比较其性能。
您可以设计自己的 MATLAB 代码,以避免与数组布局相关的潜在低效情况。效率低下可能是由以下原因造成的:
行优先布局和列优先布局之间的转换。
行优先数据的一维或线性索引。
行优先数据的重构或重新排列。
当您在同一代码或模型中混合使用行优先设定和列优先设定时,或当您对以行优先形式存储的数据使用线性索引时,就需要进行数组布局转换。当您仿真模型或为使用列优先的模型生成代码时,如果该模型包含使用行优先的 MATLAB Function 模块,则软件会根据需要将输入数据转换为行优先,并将输出数据转换回列优先,反之亦然。
对于给定的数组布局选择项,低效可能是优化不足的函数或算法导致的。如果函数或算法对于另一种布局更高效,您可以通过调用 coder.rowMajor
或 coder.columnMajor
将它嵌入到另一个函数中来强制实现该布局。
线性索引使用列优先数组布局
代码生成器遵循线性索引的 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.rowMajor
| coder.columnMajor
| coder.isColumnMajor
| coder.isRowMajor