【问题标题】:Matrix of unknown length in MATLAB?MATLAB中未知长度的矩阵?
【发布时间】:2010-12-05 14:36:39
【问题描述】:

我正在尝试设置一个具有两列的可变长度零矩阵,我可以在其中输出 while 循环的结果(目的是使用它来存储欧拉方法的步长数据和调整的时间步长)。长度将由循环的迭代次数决定。

我想知道是否有一种方法可以在我运行循环时执行此操作,或者我是否需要在开始时对其进行设置,以及如何执行此操作。

【问题讨论】:

标签: matlab matrix variable-length


【解决方案1】:

另一种在考虑性能的同时仍努力提高空间效率的方法是大批量预分配内存,并根据需要添加更多批次。如果您必须在事先不知道有多少的情况下添加大量项目,这非常适合。

BLOCK_SIZE = 2000;                          % initial capacity (& increment size)
listSize = BLOCK_SIZE;                      % current list capacity
list = zeros(listSize, 2);                  % actual list
listPtr = 1;                                % pointer to last free position

while rand<1-1e-5                           % (around 1e5 iterations on avrg)
  % push items on list
  list(listPtr,:) = [rand rand];            % store new item
  listPtr = listPtr + 1;                    % increment position pointer

  % add new block of memory if needed
  if( listPtr+(BLOCK_SIZE/10) > listSize )  % less than 10%*BLOCK_SIZE free slots
    listSize = listSize + BLOCK_SIZE;       % add new BLOCK_SIZE slots
    list(listPtr+1:listSize,:) = 0;
  end
end
list(listPtr:end,:) = [];                   % remove unused slots

编辑:作为时间比较,请考虑以下情况:

  1. 与上述相同的代码进行了 50000 次迭代。
  2. 预先分配整个矩阵:list = zeros(50000,2); list(k,:) = [x y];
  3. 动态添加向量到矩阵:list = []; list(k,:) = [x y];

在我的机器上,结果是:

1) 经过的时间是 0.080214 秒。
2) 经过时间为 0.065513 秒。
3) 经过的时间是 24.433315 秒。


更新:

根据 cmets 中的讨论,我使用最新的 R2014b 版本重新运行了一些测试。结论是最近的 MATLAB 版本大大提高了自动数组增长的性能!

但是有一个问题;数组必须在最后一个维度上增长(在二维矩阵的情况下是列)。这就是为什么在没有预分配的情况下像最初预期的那样追加行仍然太慢。这就是上面提出的解决方案真正有用的地方(通过批量扩展数组)。

查看完整的测试集:https://gist.github.com/amroamroamro/0f104986796f2e0aa618

【讨论】:

  • 哇哦!一个有见地的点+测量来证实它。谢谢。
  • 附注大多数可变大小的方法(如字符串类)不使用固定的块大小,而是将大小增加一个乘法因子 K(通常 K=2)。这将分配步骤的数量限制为 O(log N),如果您关心内存效率,您始终可以选择 K = 1.2 或 1.1 并处理数学计算命中以权衡效率/分配步骤的数量。
  • 你可能是对的..你可以很容易地修改代码来做到这一点。还可以调整许多参数:何时增加大小、增加多少,甚至可能是一个增长因素(从 K=1.1 开始,增加到 2)
  • 我有一个关于这个的问题,这可以转换成一个类吗?
  • @masad:当然可以!我在 File Exchange 上看到过一些类似的提交。这是 John D'Errico 的一篇文章,他简要讨论了here:growdata/growdata2。在内部,它的实现方式与我的不同,但您可以模仿界面。
【解决方案2】:

如果列数是固定的,您可以随时向矩阵添加行(在循环内)

例如

while (....)
   .....
   new_row =[x y] ; % new row with values x & y
   mat = [mat ; new_row]; 

当然,如果您知道 while 循环之前的迭代次数,那么预先分配矩阵会更有效

【讨论】:

  • 非常感谢!这对我来说很有意义。你认为对于一个编程单元,他们会教我们一些,但他们却把我们扔给了狼。谢谢你救了我:)
  • 对上面代码的最后一行使用替代语法可以更明确地表明您正在扩展矩阵:mat(end+1,:) = new_row;
  • 在stackoverflow.com/questions/49256309/…上查看一些速度提示
【解决方案3】:

MATLAB 使用动态类型和自动内存管理。这意味着,您无需在使用前声明固定大小的矩阵 - 您可以随时更改它,MATLAB 将为您动态分配内存。

但是首先为矩阵分配内存并然后使用它方式更有效。但是,如果您的程序需要这种灵活性,那就去吧。

我猜你需要不断地将行附加到你的矩阵中。以下代码应该可以工作。

Matrix = [];

while size(Matrix,1) <= 10
    Matrix = [Matrix;rand(1,2)];
end

disp(Matrix);

在这里,每次您添加新行时,我们都会动态地重新分配 Matrix 所需的空间。例如,如果您事先知道要拥有的行数的上限,则可以声明 Matrix = zeros(20,2),然后将每一行增量插入矩阵。

% Allocate space using the upper bound of rows (20)
Matrix = zeros(20,2);
k = 1;
for k = 1:10
   Matrix(k,:) = rand(1,2);
end
% Remove the rest of the dummy rows
Matrix(k+1:end,:) = [];

【讨论】:

  • +1 我一直用这个。请注意,您也可以只使用计数器,Matlab 会增加数组。
  • 我开始了解您在做什么以及为什么它有效。很有帮助,谢谢。
【解决方案4】:

Jacob 发布的相同内容的另一种风格。

for counter = 1:10
    Matrix(counter,:) = rand(1,2);
end
disp(Matrix);

关于此的一个“好”的事情是您可以猜测最小尺寸以帮助提高性能。

这可能也很有趣:http://www.mathworks.com/help/matlab/math/resizing-and-reshaping-matrices.html#f1-88760

【讨论】:

    猜你喜欢
    • 2015-08-02
    • 1970-01-01
    • 2012-04-26
    • 2017-01-26
    • 2011-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多