2
votes

I'm running a MatLab script which has a couple of nested loops, and am being told to preallocate some of my vectors and arrays.

I've been able to find how to do this for, say, cells or doubles, but am having difficulty finding out how to pre-allocate arrays for other data types.

Specifically, I'm using vectors and arrays containing SimBiology objects.

So we have:

  • allModels as a vector of 100 SimBiology models

  • resultsData as a vector of SimData

  • allResults as a m x n SimData matrix

I think that all of these could benefit from preallocation - at present I'm seeing my memory use increase dramatically as I run the script, presumably due to reallocation and memory fragmentation, and released memory not being cleaned up/returned to the OS effectively.

I'm quite new to matlab, so my apologies if the answer should be obvious, or if I've not given enough info... Thanks for any help!

Cheers

1

1 Answers

4
votes

I'll give you some pre-allocation tips in a moment, but I first want to point out that your memory usage is more likely due to SimBiology models remaining in memory until you exit MATLAB. SimBiology models behave pretty differently from cells or doubles in a couple of important ways:

  1. SimBiology models are "handle objects" as opposed to "value objects." You can read more in the MATLAB documentation about handle and value objects, but the key point here is that multiple variables can simultaneously refer to the same in-memory SimBiology model.
  2. SimBiology models remain in memory until they are explicitly deleted. You can always get access to all in-memory SimBiology models using the function sbioroot. To remove a SimBiology model from memory, you must call the delete method, e.g. delete(modelObj). If you want to delete all SimBiology models at once, you can just call the function sbioreset (but use this function with caution!).

Now, on to pre-allocation. A "reversed for loop" is one way you can pre-allocate any data type (without needing to learn a specific function for each data type). The idea is to take advantage of MATLAB's automatic array allocation in a way that initially allocates the array with its maximum size. Here's a silly example that makes a vector of the first 5 powers of 2:

for ind = 5:-1:1
  squares(ind) = ind^2;
end

I say this is a silly example, because it would be better implemented in MATLAB as (1:5)^2. Nonetheless, I hope it gets across the idea of allocating with reverse for loops.

For your particular case of working with SimBiology, you will want to combine explicit deletion of SimBiology models and reverse for loops. Your code might look something like this:

% Note the reverse for loop below
for modelIndex = 100:-1:1
  % First, load the model
  % Option 1: Load your models from a list of SBML files stored in sbmlFileNames
  allModels(modelIndex) = sbmlimport(sbmlFileNames{modelIndex})
  % Option 2: Load your models from a list of sbproj files stored in projFileNames
  loadedProject = sbioloadproject(projFileNames{modelIndex});
  allModels(modelIndex) = loadedProject.m1;
  % Option 3: Explicitly create your model
  allModels(modelIndex) = sbiomodel(['Model ' num2str(modelIndex)]);
  % Of course, you'll need to customize each model somehow

  % Store a "baseline" simulation of each in resultsData
  resultsData(modelIndex) = sbiosimulate(allModels(modelIndex));

  % Now create the matrix of SimData
  % Note the reverse for loop below
  for variantIndex = 20:-1:1
    % Setup for the modified simulation.
    % One option: Use some previously defined variant objects stored in variantList
    allResults(modelIndex, variantIndex) = ...
      sbiosimulate(allModels(modelIndex), variantList(variantIndex));
  end
end

% Once you are done, delete SimBiology models to free memory
delete(allModels)

Also feel free to contact MathWorks Technical Support if you have additional questions. (I'm one of the developers of SimBiology, and I always appreciate the opportunity hear what our users are doing and find ways to make life easier for them.)

-Arthur