中的行主要数据接口MATLAB函数块
数组布局对于集成、可用性和性能非常重要。金宝app动态仿真模块®默认情况下使用列主布局MATLAB函数块。然而,许多设备、传感器和库对其数据使用行主数组布局。方法可以将模型直接应用于此数据coder.ceval
中的行主布局函数MATLAB函数块。
数组布局也会影响性能。对于特定的数组布局,许多算法都能更有效地执行内存访问。
模拟和代码生成中的行-主布局
为MATLAB函数块中,可以在块中指定行-主数组布局。此规范发生在函数级,并不改变函数外部模型的数组布局。控件中指定的数组布局MATLAB函数块既适用于模拟,也适用于C/ c++代码生成。看到在函数和类中指定数组布局.
用于C/ c++代码生成使用金宝app仿真软件编码器™和嵌入式编码器®在软件中,您可以在模型级别指定数组布局,这是由金宝appMATLAB函数块。有关在模型级别控制数组布局的更多信息,请参见矩阵和数组的代码生成(金宝app仿真软件编码器)。阵列布局的模型代码生成设置对仿真没有影响。看到阵列布局(金宝app仿真软件编码器)。中使用行-主布局的例子MATLAB函数块用于代码生成,请参见为包含MATLAB函数块的模型生成行主代码(金宝app仿真软件编码器)。
为MATLAB函数块中,函数级的数组布局规范优先于模型的数组布局规范。然而,对于全局变量和持久变量,模型的数组布局规范优先。
数组布局转换
MATLAB®和Sim金宝appulink默认以列为主布局存储数据。当您在不同的功能和不同的边界指定不同的数组布局时,软件会根据需要自动插入数组布局转换。
例如,当您模拟一个模型或为使用列主布局的模型生成代码时,并且该模型包含一个MATLAB函数使用行为主布局的块,然后软件根据需要将块输入数据转换为行为主,并将块输出数据转换为列为主。数组布局转换会影响性能。有关数组布局的性能考虑因素的更多信息,请参见行-主阵列布局的代码设计.
阵列布局与算法效率
对于某些算法,行主布局提供了更有效的内存访问。考虑这个用于两个矩阵相加的函数。该算法通过显式的行和列遍历执行加法。
函数[S] = addMatrix(A,B) code . rowmajor;S = 0 (size(A));为row = 1:size(A,1)为坳= 1:尺寸(2)年代(行,坳)=(行,上校)+ B(行,坳);结束结束
如果你在MATLAB函数块,代码生成的结果是这个函数的C代码:
.../*生成addMatrix的代码,使用row-major */ for (row = 0;行< 20;Row ++) {for (col = 0;Col < 10;col++) {S[col + 10 * row] = A[col + 10 * row] + B[col + 10 * row];}}…
数组被生成的代码索引,使用公式:
[col + 10 * row]
因为数组存储在行主布局中,相邻的内存元素由单列增量分隔。的步幅因为算法等于1。步幅长度是连续访问内存之间的内存元素的距离。更短的步幅可以提供更有效的内存访问。
对数据使用列-主布局会导致更长的步幅和更低的内存访问效率。要查看这种比较,请考虑生成的C代码addMatrix
它使用了列主布局:
.../*为addMatrix使用column-major生成代码*/ for (row = 0;行< 20;Row ++) {for (col = 0;Col < 10;{S[行+ 20 * col] = A[行+ 20 * col] + B[行+ 20 * col];}}…
在列-主布局中,列元素在生成代码的内存中是连续的。相邻的内存元素由单行增量分隔,并按公式进行索引:
[row + 20 * col]
然而,该算法遍历内部for循环中的列。因此,列为主的C代码必须为每次连续的内存访问跨出20个元素。
提供最有效内存访问的数组布局取决于算法。对于该算法,数据的行主布局提供了更有效的内存访问。该算法逐行遍历数据。因此,行主存储更有效。
n维数组的行-主布局
可以对n维数组使用行主布局。当数组以行为主布局存储时,来自最后(最右边)维度或索引的元素在内存中是连续的。在主列布局中,第一个(最左)维度或索引的元素是连续的。
考虑示例函数addMatrix3D
它接受三维输入。
函数[S] = addMatrix3D(A,B) code . rowmajor;S = 0 (size(A));为i = 1:size(A,1)为j = 1:size(A,2)为k = 1:size(A,3) S(i,j,k) = A(i,j,k) + B(i,j,k);结束结束结束结束
代码生成器生成以下C代码:
.../* row-major layout */ for (i = 0;I < 20;i++) {for (j = 0;J < 10;j++) {for (k = 0;K < 5;k + +) {S [(k + 5 * j) + 50 *我]= [(k + 5 * j) + 50 *我]+ B [(k + 5 * j) + 50 *我);}}}
在行主布局中,相邻的内存元素由最后一个索引的单个增量分隔,k
.内部for循环遍历内存中仅由一个位置分隔的相邻元素。
删除coder.rowMajor
调用并生成使用列主布局的C代码:
.../*列主布局*/ for (i = 0;I < 20;i++) {for (j = 0;J < 10;j++) {for (k = 0;K < 5;k + +) {S [(i + 20 * j) + 200 * k] = [(i + 20 * j) + 200 * k) + B [(i + 20 * j) + 200 * k);}}}
在主列布局中,相邻元素由第一个索引的单个增量分隔,我
.内部for循环现在在内存中被200个位置分隔的相邻元素上迭代。较长的跨步长度会由于缓存失误而导致性能下降。
因为算法遍历最后一个索引,k
,在内部for循环中,对于使用列主布局的生成代码,步长要长得多。对于该算法,数据的行主布局提供了更有效的内存访问。
在外部函数调用中指定数组布局
若要调用期望以特定布局存储数据的外部C/ c++函数,请使用coder.ceval
与布局
语法。如果不使用此语法,则默认假定外部函数输入和输出使用列主布局。
考虑一个使用行主布局的外部C函数称为myCFunctionRM
.要将此函数集成到代码中,请使用“布局:rowMajor”
或“行”
选择。该选项确保输入和输出数组按行主顺序存储。代码生成器根据需要自动插入数组布局转换。
coder.ceval (“布局:rowMajor”,“myCFunctionRM”, coder.ref coder.ref ())
在一个使用行为主布局的MATLAB函数中,您可能会寻求调用一个设计用于使用列为主布局的外部函数。在本例中,使用“布局:columnMajor”
或“上校”
选择。
coder.ceval (“布局:columnMajor”,“myCFunctionCM”, coder.ref coder.ref ())
可以在相同的代码中执行行大函数和列大函数调用。考虑函数myMixedFn1
举个例子:
函数[E] = myMixedFn1(x,y)% # codegencoder.rowMajor;%指定ceval调用的返回参数类型D = 0 (size(x));E = 0 (size(x));%包括使用row-major和column-major的外部C函数coder.cinclude (“addMatrixRM.h”);coder.updateBuildInfo (“addSourceFiles”,“addMatrixRM.c”);coder.cinclude (“addMatrixCM.h”);coder.updateBuildInfo (“addSourceFiles”,“addMatrixCM.c”);调用C函数,使用行主顺序coder.ceval (“布局:rowMajor”,“addMatrixRM”,...coder.rref (x) coder.rref (y), coder.wref (D));%调用C函数,使用列主序coder.ceval (“布局:columnMajor”,“addMatrixCM”,...coder.rref (x) coder.rref (D), coder.wref (E));结束
外部文件是:
另请参阅
coder.ceval
|coder.columnMajor
|coder.isColumnMajor
|coder.isRowMajor
|coder.rowMajor
相关的话题
- 在函数和类中指定数组布局
- 行-主阵列布局的代码设计
- 矩阵和数组的代码生成(金宝app仿真软件编码器)