主要内容

生成使用行-主数组布局的代码

数组布局对于集成、可用性和性能非常重要。代码生成器生成默认情况下使用列主布局的代码。然而,许多设备、传感器和库对其数据使用行主数组布局。您可以通过生成使用行-主布局的代码,直接将代码应用于此数据。数组布局也会影响性能。对于特定的数组布局,许多算法都能更有效地执行内存访问。

属性可以在命令行指定行-主数组布局,使用代码生成配置属性也可以MATLAB®编码器™你也可以为单个函数和类指定行为主布局或列为主布局。入口点(顶级)函数的输入和输出都必须使用相同的数组布局。

指定行布局

考虑这个用于两个矩阵相加的函数。该算法通过显式的行和列遍历执行加法。

函数[S] = addMatrix (A, B)% # codegenS = 0(大小(A));行= 1:尺寸(1)坳= 1:尺寸(2)年代(行,坳)=(行,上校)+ B(行,坳);结束结束

生成C代码addMatrix通过使用-rowmajor选择。方法指定输入参数的形式arg游戏选项并启动代码生成报告。

codegenaddMatrixarg游戏{的(20、10)的(20、10)}配置:自由-launchreport-rowmajor

方法来配置代码的行主布局RowMajor参数中的代码生成配置对象。可以对任何类型的配置对象使用此参数:自由墨西哥人dll,或exe

cfg = coder.config (“自由”);cfg。RowMajor = true;codegenaddMatrixarg游戏{的(20、10)的(20、10)}配置cfg-launchreport

代码生成的结果如下C代码:

.../*生成addMatrix的代码,使用row-major */ for (row = 0;行< 20;Row ++) {for (col = 0;坳< 10;col++) {S[col + 10 * row] = A[col + 10 * row] + B[col + 10 * row];}}…

方法指定行主布局MATLAB编码器应用:

  1. 打开生成对话框。在生成代码页面,点击生成箭头

  2. 点击更多的设置

  3. 内存选项卡,设置阵列布局:

要验证生成的代码是否使用了行为主布局,请将生成代码中的数组索引与使用列为主布局的代码中的数组索引进行比较。您还可以生成使用n维索引的代码。n维索引可以使数组布局的差异更加明显。有关更多信息,请参见生成使用n维索引的代码

MATLAB默认以列为主布局存储数据。当您调用一个使用行-主布局的生成MEX函数时,软件会自动将输入数据从列-主布局转换为行-主布局。从MEX函数返回的输出数据被转换回列主布局。为独立的自由dll,exe代码生成,代码生成器假定入口点函数的输入和输出使用与函数相同的数组布局存储。

阵列布局与算法效率

对于某些算法,行主布局提供了更有效的内存访问。考虑所示的C代码addMatrix它使用行主布局。数组被生成的代码索引,使用公式:

[col + 10 * row]

因为数组存储在行主布局中,相邻的内存元素由单列增量分隔。的步幅因为算法等于1。步幅长度是连续访问内存之间的内存元素的距离。更短的步幅可以提供更有效的内存访问。

对数据使用列-主布局会导致更长的步幅和更低的内存访问效率。要查看这个比较,生成使用列主布局的代码:

codegenaddMatrixarg游戏{的(20、10)的(20、10)}配置:自由-launchreport

代码生成生成以下C代码:

.../*为addMatrix使用column-major生成代码*/ for (row = 0;行< 20;Row ++) {for (col = 0;坳< 10;{S[行+ 20 * col] = A[行+ 20 * col] + B[行+ 20 * col];}}…

在列-主布局中,列元素在生成代码的内存中是连续的。相邻的内存元素由单行增量分隔,并按公式进行索引:

[row + 20 * col]

然而,该算法遍历内部for循环中的列。因此,列为主的C代码必须为每次连续的内存访问跨出20个元素。

提供最有效内存访问的数组布局取决于算法。对于该算法,数据的行主布局提供了更有效的内存访问。该算法逐行遍历数据。因此,行主存储更有效。

n维数组的行-主布局

可以对n维数组使用行主布局。当数组以行为主布局存储时,来自最后(最右边)维度或索引的元素在内存中是连续的。在主列布局中,第一个(最左)维度或索引的元素是连续的。

考虑示例函数addMatrix3D它接受三维输入。

函数[S] = addMatrix3D (A, B)% # codegenS = 0(大小(A));i = 1:尺寸(1)j = 1:尺寸(2)k = 1:size(A,3) S(i,j,k) = A(i,j,k) + B(i,j,k);结束结束结束结束

生成使用行为主布局的代码:

codegenaddMatrix3Darg游戏{(20、10、5)、人(20、10、5)}配置:自由-launchreport-rowmajor

代码生成器生成以下C代码:

.../* row-major layout */ for (i = 0;我< 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循环遍历内存中仅由一个位置分隔的相邻元素。比较使用列主布局生成的代码的区别:

.../*列主布局*/ for (i = 0;我< 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)% # codegen%指定ceval调用的返回参数类型D = 0(大小(x));E = 0(大小(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));结束

外部文件是:

addMatrixRM.h

addMatrixRM.c

addMatrixCM.h

addMatrixCM.c

要生成代码,输入:

codegen配置:自由myMixedFn1arg游戏{的(20、10)的(20、10)}-rowmajor-launchreport

另请参阅

|||||

相关的话题

Baidu
map