诊断并修复可变大小数据错误
诊断并修复大小不匹配错误
问题:将可变大小矩阵赋给固定大小矩阵
在生成的代码中,不能将可变大小矩阵赋给固定大小矩阵。请参考如下示例:
function Y = example_mismatch1(n) %#codegen assert(n < 10); B = ones(n,n); A = magic(3); A(1) = mean(A(:)); if (n == 3) A = B; end Y = A;
编译此函数会产生以下错误:
??? Dimension 1 is fixed on the left-hand side but varies on the right ...
可通过几种方法修复此错误:
通过添加
coder.varsize
构造,允许矩阵A
增大:function Y = example_mismatch1_fix1(n) %#codegen coder.varsize('A'); assert(n < 10); B = ones(n,n); A = magic(3); A(1) = mean(A(:)); if (n == 3) A = B; end Y = A;
通过修改
assert
语句,将矩阵B
的大小显式限制为 3×3:function Y = example_mismatch1_fix2(n) %#codegen coder.varsize('A'); assert(n == 3) B = ones(n,n); A = magic(3); A(1) = mean(A(:)); if (n == 3) A = B; end Y = A;
使用显式索引使
B
与A
大小相同:function Y = example_mismatch1_fix3(n) %#codegen assert(n < 10); B = ones(n,n); A = magic(3); A(1) = mean(A(:)); if (n == 3) A = B(1:3, 1:3); end Y = A;
问题:空矩阵经过重构以匹配可变大小设定
如果您将空矩阵 []
赋给可变大小数据,MATLAB® 可能会在生成的代码中以静默方式重构数据以匹配 coder.varsize
设定。例如:
function Y = test(u) %#codegen Y = []; coder.varsize('Y', [1 10]); if u < 0 Y = [Y u]; end
在此示例中,coder.varsize
将 Y
定义为最多 10 个元素的列向量,因此其第一个维度大小固定为 1。语句 Y = []
将 Y
的第一个维度指定为 0,从而导致不匹配。赋值的右侧是空矩阵,左侧是可变大小向量。在这种情况下,MATLAB 将生成的代码中的空矩阵 Y = []
重构为 Y = zeros(1,0)
,以使其匹配 coder.varsize
设定。
问题:将隐式扩展的输出赋给固定大小变量
如果将二元运算或函数的隐式扩展输出赋给不同大小的变量,代码生成器可能会生成错误。例如:
function out = test(n) %#codegen x = ones(n,1); if mod(n,2) == 1 y = ones(n,n); x = y + x; end out = out + x(2); end
在此示例中,x
是无界向量。由于隐式扩展,对 x
和 y
的加法运算会产生无界矩阵 (Inf×Inf)。将无界矩阵赋给无界向量 x
会导致错误。
如果要使用隐式扩展的输出,请将输出赋给与输出大小相同的新变量。
如果您需要 x 保持其大小,并且不在生成的代码中应用隐式扩展,请使用 coder.sameSizeBinaryOp
来应用该运算。您还可以在函数体中调用 coder.noImplicitExpansionInFunction
,以禁用为该函数生成的代码中的隐式扩展。
隐式扩展自动扩展操作数,以便对兼容大小的数组应用二元运算。请参阅Generate Code With Implicit Expansion Enabled、Optimize Implicit Expansion in Generated Code和基本运算的兼容数组大小。
诊断并修复上界检测中的错误
问题:在矩阵构造函数中使用非常量维度
您可以通过将变量赋给具有非常量维度的矩阵定义可变大小数据。例如:
function y = dims_vary(u) %#codegen if (u > 0) y = ones(3,u); else y = zeros(3,1); end
但是,编译此函数会生成错误,因为您没有为 u
指定上界。
可通过几种方法修复此问题:
启用动态内存分配并重新编译。在代码生成过程中,当 MATLAB 对可变大小数据使用动态内存分配时,不检查上界。
如果您不想使用动态内存分配,请在第一次使用
u
之前添加一条assert
语句:function y = dims_vary_fix(u) %#codegen assert (u < 20); if (u > 0) y = ones(3,u); else y = zeros(3,1); end