Main Content

潜在差异消息

当您启用潜在差异报告时,代码生成器会报告生成的代码的行为和 MATLAB® 代码的行为之间的潜在差异。在生成独立代码之前检查并解决潜在差异有助于避免生成的代码中出现错误和不正确的答案。

以下是一些潜在差异消息:

自动维度不兼容

在生成的代码中,要运算的维度是自
动选择的,可能与 MATLAB 不同。
请考虑将工作维度显示指定为常量值。

此限制适用于接受工作维度(运算所基于的维度)作为输入的函数。在 MATLAB 和代码生成中,如果您不提供工作维度,函数会选择工作维度。在 MATLAB 中,函数选择其大小不等于 1 的第一个维度。对于代码生成,函数选择具有可变大小或不等于 1 的固定大小的第一个维度。如果该工作维度具有可变大小并且在运行时大小变为 1,则该工作维度不同于 MATLAB 中的工作维度。因此,如果启用了运行时错误检查,可能会发生错误。

例如,假设 X 是维度为 1x:3x:5 的可变大小矩阵。在生成的代码中,sum(X) 的行为类似于 sum(X,2)。在 MATLAB 中,sum(X) 的行为类似于 sum(X,2),除非 size(X,2) 为 1。在 MATLAB 中,当 size(X,2) 为 1 时,sum(X) 的行为类似于 sum(X,3)

要避免此问题,请将需要的工作维度显式指定为一个常量值。例如,sum(X,2)

mtimes 没有动态标量扩展

生成的代码执行一般矩阵乘法。
如果可变大小矩阵操作数在运行
时变为标量,维度仍必须一致。
不会自动切换到标量乘法。

A*B 相乘为例。如果代码生成器发现 A 是标量,B 是矩阵,则代码生成器会生成用于标量矩阵乘法的代码。但是,如果代码生成器发现 AB 是可变大小矩阵,它会生成用于一般矩阵乘法的代码。在运行时,如果发现 A 是标量,则生成的代码不会更改其行为。因此,当启用运行时错误检查时,可能会出现大小不匹配错误。

矩阵-矩阵索引

对于使用矩阵对矩阵进行索引的方式 matrix1(matrix2),
代码生成器假设结果的大小与 matrix2 相同。
如果 matrix1 和 matrix2 在运行时是向量,其方向
必须匹配。

在矩阵-矩阵索引中,使用的是一个矩阵(索引矩阵)对另一个矩阵(数据矩阵)进行索引。在 MATLAB 中,矩阵-矩阵索引的一般规则是结果的维度与索引矩阵的维度相同。例如,如果 AB 是矩阵,则 size(A(B)) 等于 size(B)。然而,当 AB 是向量时,MATLAB 会应用不同的规则。当执行向量-向量索引时,结果的方向与数据矩阵的方向相同。例如,如果 A 是 1×5,B 是 3×1,则 A(B) 是 1×3。

代码生成器尝试应用与 MATLAB 相同的矩阵-矩阵索引规则。如果 AB 在代码生成时是可变大小矩阵,则代码生成器遵循一般的 MATLAB 索引规则,并假设 size(A(B)) 等于 size(B)。在运行时,如果 AB 是方向不同的向量,则此假设不正确。因此,如果启用了运行时错误检查,可能会发生错误。

要避免这种运行时错误,请尝试以下解决方案之一:

  • 如果 AB 在运行时是固定大小矩阵,则在代码生成时将此矩阵定义为固定大小。

  • 如果 AB 在运行时均为向量,请确保其方向匹配。

  • 如果您的代码在运行时特意接受具有不同方向的矩阵和向量,请包含对向量-向量索引进行显式检查,并强制向量具有相同的方向。例如,使用 isvector 函数确定 AB 是否均为向量,如果是,则使用 colon 运算符强制这两个向量均为列向量。

    ...
    if isvector(A) && isvector(B)
        Acol = A(:);
        Bcol = B(:);
        out = Acol(Bcol);
    else
        out = A(B);
    end
    ...

向量-向量索引

对于使用向量对向量进行索引的方式 vector1(vector2),
代码生成器假设结果的方向与 vector1 相同。
如果 vector1 在运行时是标量,则 vector2 的方向
必须与 vector1 匹配。

在向量-向量索引中,使用一个向量(索引向量)对另一个向量(数据向量)进行索引。在 MATLAB 中,向量-向量索引的规则是结果向量的方向与数据向量的方向相同。例如,如果 A 是 1×5,B 是 3×1,则 A(B) 是 1×3。但是,如果 A 是标量,则此规则不适用。如果 A 是标量,则 A(B) 的方向与索引向量 B 的方向相同。

代码生成器尝试应用与 MATLAB 相同的向量-向量索引规则。如果 A 在代码生成时是可变大小向量,则代码生成器假设 A(B) 的方向与 A 的方向相同。但是,此假设是错误的,如果同时满足以下两个条件,就会发生运行时错误:

  • 在代码生成时,A 的方向与 B 的方向不匹配。

  • 在运行时,A 是标量,B 是向量。

要避免这种运行时错误,请尝试以下解决方案之一:

  • 如果 A 在运行时是标量,则在代码生成时将 A 定义为标量。

  • 如果 AB 在代码生成时定义为向量,请确保其方向相同。

  • 如果 AB 在代码生成时是具有不同方向的可变大小向量,请确保 A 在运行时不是标量。

  • 如果 AB 在代码生成时是具有不同方向的可变大小向量,请确保 B 在运行时不是向量。

循环索引溢出

生成的代码假设循环索引不会在循环的最后一次
迭代中溢出。如果循环索引溢出,可能会出现
无限循环。

假设 for 循环结束值等于或接近循环索引数据类型的最大值或最小值。在生成的代码中,循环索引的最后一次递增或递减可能会导致索引变量溢出。索引溢出可能导致无限循环。

启用内存完整性检查时,如果代码生成器检测到循环索引可能溢出,它会报告错误。软件错误检查是保守型的。它可能会误报循环索引溢出。默认情况下,内存完整性检查对 MEX 代码启用,对独立 C/C++ 代码禁用。请参阅为什么要在 MATLAB 中测试 MEX 函数?Generate Standalone C/C++ Code That Detects and Reports Run-Time Errors

为了避免循环索引溢出,请使用下表中的解决方法。

可能导致溢出的循环条件解决方法
  • 循环索引递增 1。

  • 结束值等于整数类型的最大值。

如果循环不必覆盖整数类型的全部范围,请重写循环,使结束值不等于整数类型的最大值。例如,将:

N=intmax('int16')
for k=N-10:N
替换为:
for k=1:10

  • 循环索引递减 1。

  • 结束值等于整数类型的最小值。

如果循环不必覆盖整数类型的全部范围,请重写循环,使结束值不等于整数类型的最小值。例如,将:

N=intmin('int32')
for k=N+10:-1:N
替换为:
for k=10:-1:1

  • 循环索引递增或递减 1。

  • 起始值等于整数类型的最小值或最大值。

  • 结束值等于整数类型的最大值或最小值。

如果循环必须覆盖整数类型的全部范围,请将循环的开始值、步长值和结束值的类型转换为更大的整数或双精度值。例如,重写:

M= intmin('int16');
N= intmax('int16');
for k=M:N
	% Loop body
end
为:
M= intmin('int16');
N= intmax('int16');
for k=int32(M):int32(N)
	% Loop body
end

  • 循环索引按不等于 1 的值递增或递减。

  • 在最后一次循环迭代中,循环索引不等于结束值。

重写循环,使最后一次循环迭代中的循环索引等于结束值。

相关主题