Matrix of unknown length in MATLAB?

Flick picture Flick · Oct 10, 2009 · Viewed 56.1k times · Source

I'm trying to set up a zero matrix of variable length with two columns into which I can output the results of a while loop (with the intention of using it to store the step data from Euler's method with adjusted time-steps). The length will be determined by the number of iterations of the loop.

I'm wondering if there's a way I can do this while I'm running the loop or whether I need to set it up to begin with, and how to go about doing that.

Answer

Amro picture Amro · Oct 10, 2009

Another approach that has performance in mind while still trying to be space-efficient, is to preallocate memory in large batches, adding more batches as needed. This is well suited if you have to add a large number of items without knowing how many beforehand.

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

EDIT: As a time comparison, consider the following cases:

  1. The same code as above done for 50000 iterations.
  2. Preallocating the entire matrix beforehand: list = zeros(50000,2); list(k,:) = [x y];
  3. Dynamically adding vectors to matrix: list = []; list(k,:) = [x y];

On my machine, the results were:

1) Elapsed time is 0.080214 seconds.
2) Elapsed time is 0.065513 seconds.
3) Elapsed time is 24.433315 seconds.


Update:

Following discussions in the comments, I've rerun some tests using the latest R2014b release. The conclusion is that recent versions of MATLAB has greatly improved the performance of automatic array growth!

However there is a catch; the array must be growing across the last dimension (columns in the case of 2D matrices). That's why appending rows like originally intended is still too slow without preallocation. This is where the above proposed solution can really help (by extending the array in batches).

See here for the full set of tests: https://gist.github.com/amroamroamro/0f104986796f2e0aa618