25

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

我想知道在我运行循环时是否有办法做到这一点,或者我是否需要从一开始就设置它,以及如何去做。

4

4 回答 4

47

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

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 秒。


更新:

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

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

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

于 2009-10-10T21:15:27.570 回答
15

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

例如

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

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

于 2009-10-10T14:44:18.093 回答
7

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,:) = [];
于 2009-10-10T14:41:04.263 回答
4

雅各布发布的同一件事的另一种味道。

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

于 2009-10-10T14:48:38.193 回答