潜在差异信息
当你启用潜在的差异代码生成器报告生成的代码的行为和MATLAB的行为之间的潜在差异®代码。在生成独立代码之前检查和处理潜在的差异可以帮助您避免在所生成的代码中出现错误和不正确的答案。
以下是一些潜在的差异信息:
自动尺寸不兼容
在生成的代码中,要操作的维度是自动选择的,可能与MATLAB不同。考虑将工作维度显式指定为常量值。
此限制适用于将工作维度(操作所沿的维度)作为输入的函数。在MATLAB和代码生成中,如果您不提供工作维度,函数将选择它。在MATLAB中,函数选择大小不等于1的第一个维度。对于代码生成,该函数选择第一个具有可变大小或具有不等于1的固定大小的维度。如果工作维的大小是可变的,并且在运行时变为1,那么工作维与MATLAB中的工作维是不同的。因此,当启用运行时错误检查时,就会发生错误。
例如,假设X
变大小矩阵是有维的吗1 x: 3 x: 5
.在生成的代码中,总和(X)
表现得像总和(X, 2)
.在MATLAB中,总和(X)
表现得像总和(X, 2)
除非大小(X, 2)
是1。在MATLAB中,当大小(X, 2)
是1,总和(X)
表现得像总和(X, 3)
.
要避免此问题,可以显式地将预期的工作维度指定为常量值。例如,总和(X, 2)
.
mtimes无动态标量扩展
生成的代码执行一般的矩阵乘法。如果可变大小的矩阵操作数在运行时变成标量,维数必须仍然一致。不会自动切换到标量乘法。
考虑乘法A * B
.如果代码生成器知道这一点一个
是标量和B
是矩阵,则代码生成器生成用于标量矩阵乘法的代码。但是,如果代码生成器知道一个
而且B
都是可变大小的矩阵,它生成的代码用于一般矩阵的乘法运算。在运行时,如果一个
结果是标量,生成的代码不会改变其行为。因此,当启用运行时错误检查时,可能会发生大小不匹配错误。
矩阵与矩阵的索引
为了用矩阵matrix1(matrix2)索引一个矩阵,代码生成器假定结果与matrix2具有相同的大小。如果matrix1和matrix2在运行时是向量,它们的方向必须匹配。
在矩阵-矩阵索引中,您使用一个矩阵索引到另一个矩阵。在MATLAB中,矩阵-矩阵索引的一般规则是结果的大小和方向与索引矩阵的大小和方向相匹配。例如,如果一个
而且B
矩阵,大小((B))
=大小(B)
.当一个
而且B
是向量,MATLAB应用了一个特殊的规则。特殊的向量-向量索引规则是结果的方向就是数据矩阵的方向。例如,i一个
是1乘5和B
是3乘1吗(B)
1×3。
代码生成器应用与MATLAB相同的矩阵-矩阵索引规则。如果一个
而且B
是可变大小的矩阵,为了应用矩阵-矩阵索引规则,代码生成器假设大小((B))
=大小(B)
.如果在运行时,一个
而且B
变成矢量并且有不同的方向,那么假设是不正确的。因此,当启用运行时错误检查时,就会发生错误。
为避免此问题,可以使用冒号操作符进行索引,强制将数据转换为向量。例如,假设您的代码在运行时有意在向量和规则矩阵之间切换。您可以显式地检查向量-向量索引。
...如果isvector(A) && isvector(B) C = A(:);D = c (b (:));其他的D = a (b);结束...
第一个分支中的索引指定了这一点C
而且B (:)
是编译时向量。因此,代码生成器应用索引规则将一个向量与另一个向量进行索引。结果的方向就是数据向量的方向,C
.
向量索引
为了用向量vector1(vector2)索引一个向量,代码生成器假定结果将具有与vector1相同的方向。如果vector1在运行时是一个标量,则vector2的方向必须与vector1匹配。
在MATLAB中,矢量-矢量索引的特殊规则是结果的方向是数据向量的方向。例如,如果一个
是1乘5和B
是3乘1吗(B)
1×3。但是,如果是数据向量一个
是标量,那么方向呢(B)
是指标向量的方向吗B
.
代码生成器应用与MATLAB相同的矢量-矢量索引规则。如果一个
而且B
是变大小的向量,要应用索引规则,代码生成器假定方向为B
匹配的方向一个
.在运行时,如果一个
标量和方向一个
而且B
不匹配,则假设是不正确的。因此,当启用运行时错误检查时,就会发生运行时错误。
为了避免这个问题,让向量的方向匹配。或者,通过指定行和列来索引单个元素。例如,(行、列)
.
大小不匹配
生成的代码假设左右两边的大小匹配。
标量展开是一种转换标量数据以匹配向量或矩阵数据维数的方法。如果一个操作数是标量,而另一个不是,标量展开将标量应用于另一个操作数的每个元素。
在代码生成期间,标量展开规则将应用,除非操作两个可变大小的表达式。在这种情况下,两个操作数的大小必须相同。即使其中一个可变大小表达式在运行时是标量,生成的代码也不会执行标量展开。因此,当启用运行时错误检查时,就会发生运行时错误。
考虑这个函数:
函数Y = scalar_exp_test_err1(u)% # codegenY = ones(3);开关u情况下0 z = 0;情况下1 z = 1;否则Z = 0 (3);结束Y (:) = z;
当您为这个函数生成代码时,代码生成器将确定这一点z
变量大小的上限是3.
.
如果使用u
如果等于0或1,则生成的代码不会执行标量展开z
在运行时为标量。因此,当启用运行时错误检查时,就会发生运行时错误。
scalar_exp_test_err1_mex(0)下标赋值维度不匹配:[9]~=[1]。scalar_exp_test_err1(第11行)中的错误y(:) = z;
要避免此问题,请使用索引强制z
为标量值。
函数Y = scalar_exp_test_err1(u)% # codegenY = ones(3);开关u情况下0 z = 0;情况下1 z = 1;否则Z = 0 (3);结束Y (:) = z(1);
循环索引溢出
生成的代码假定循环索引不会在循环的最后一次迭代中溢出。如果循环索引溢出,就会发生无限循环。
假设a为
-loop结束值等于或接近循环索引数据类型的最大值或最小值。在生成的代码中,循环索引的最后一个递增或递减可能导致索引变量溢出。索引溢出可能导致无限循环。
当启用内存完整性检查时,如果代码生成器检测到循环索引可能溢出,它将报告一个错误。软件错误检查比较保守。它可能错误地报告循环索引溢出。默认情况下,对MEX代码启用内存完整性检查,对独立C/ c++代码禁用内存完整性检查。看到为什么在MATLAB中测试MEX函数?而且独立C/ c++代码中的运行时错误检测和报告.
要避免循环索引溢出,请使用本表中的变通方法。
导致潜在溢出的循环条件 | 解决方案 |
---|---|
|
如果循环不必覆盖整型的全部范围,则重写循环,使结束值不等于整型的最大值。例如,replace: N=intmax('int16') for k=N-10:N k = 1:10 |
|
如果循环不必覆盖整型的全部范围,则重写循环,使结束值不等于整型的最小值。例如,replace: N=intmin('int32') for k=N+10:-1:N k = 10: 1:1 |
|
如果循环必须覆盖整型类型的全部范围,则将循环开始值、步骤值和结束值的类型强制转换为更大的整数或加倍。例如,重写: M = intmin(“int16”);N = intmax(“int16”);对于k=M:N %环体端 M = intmin(“int16”);N = intmax(“int16”);for k=int32(M):int32(N) %循环体结束 |
|
重写循环,使最后一次循环迭代中的循环索引等于结束值。 |