# Question regarding how matrices are stored in memory

8 views (last 30 days)
Marcus Rosales on 1 Sep 2021
Commented: Walter Roberson on 2 Sep 2021
I'm trying to get a simulation running which requires a big matrix ( N~400), so being smart with memory is important.
The issue: Sparing the details of what I am doing I generate this matrix, call it S, and then multiply it by a number Δ. When I do this, I get an error that matlab doesn't support array sizes this big.
Now if I decide to measure my energy scale in respect to Δ, I do not need to multiply S by it, and this matrix fits in memory. However, the number of elements in my matrix is the same... This got me thinking: how are numbers stored in matrices here?
My thoughts: I always thought that memory is allocated when you define a matrix: we have a floating point number with 64 bits of memory for each element in our matrix.
This situation makes it seem like an matrix with all zeros takes less memory than one with all 2.718281828459045's. Of course the latter requires more to describe than the former; I just thought things were preallocated.
My questions: Does matlab only keep track of the decimal and significant figures and the fewer of these the smaller? Or does it cast variables to a smaller size or something automatically? Or is it the case that what I said in the previous paragraph is right regarding allocating a fixed amount of memory at the start? Or something else...

Walter Roberson on 1 Sep 2021
I have demonstrated through experiments that at least on MacOS and Linux, if you allocate an array using zeros(), that it does not ask the operating system for all of that memory at that time. However as soon as you store even one thing into the array, it then needs to ask the operating system for all of the memory, and as a result you can get an "out of memory" error. For example,
A = zeros(2.71e9,1);
A(1) = 1;
With this online facility, 2.72e9 would give out of memory at the zeros; I have shown in the past that sometimes it would be the assignment into A(1) that would trigger the out of memory.
I did not test on MS Windows.
However, this is specifically an "out of memory" error that is generated, not an "array is too large" error.
The MATLAB model is that any array that is created and is not sparse, has all of its memory allocated at the time of creation. But that turns out not to be the case when zeros() specifically is used, as long as the array stays just 0.
If is generating an array too big error, that most often implies that Δ is a vector or array and that the inner-product operator * needs size(S,1) * size(Delta,2) memory locations for the result. So if you accidentally * a column vector and a row vector, you can be asking for a much larger result than you expect.
If is generating an array too big error, that most often implies that implicit expansion is being done. If you accidentally .* a column vector and a row vector, you could be asking for a much larger result than you expect.
So... recheck whether you are using the * (inner product) or .* (element-by-element) operator, and recheck size() of the arrays to see whether implicit expansion might be happening.
##### 2 CommentsShowHide 1 older comment
Walter Roberson on 2 Sep 2021
There are three cases for sparse arrays:
• spalloc() "creates an all-zero sparse matrix S of size m-by-n with room to hold nz nonzero elements, where nz >= 1". That is, it allocates memory to hold a sparse array with the given number of non-zero elements, but the array will read-back as 0 until you store non-zero elements into it. If you store non-zero elements into the array, then until you reach that number of them, no additional memory will need to be allocated dynamically
• the sparse matrix constructor, sparse() has an optional parameter to indicate how many non-zero values are expected. If you initialize a sparse() array without passing in that option, then sparse() does not allocate any space to store additional entries -- and if you then store into that array then the sparse class will have to build a new sparse array and copy the elements from the old one.
• any computed sparse matrix, such as multiplying an existing sparse matrix by a constant, will be created with no spare slots to store additional elements later. For example if you add two sparse arrays, both of which had slots for extra elements, then the result will not have any slots for extra elements. Extra slots in a sparse array are, in a sense, unstable, in that doing nearly any computation except direct storage into the array, can cause the extra slots to be removed.
So... if you multiply a sparse matrix by a constant, then because multiplication by 0 always gives 0 (unless you are multiplying by nan or infinity), the result cannot be more "dense" than the sparse matrix is, and so cannot take any more memory than the original sparse matrix did. In the case where the original sparse matrix had extra slots, then the result of the multiplication can end up using less memory.
Thus, the action of multiplying a sparse matrix by finite constant should not generate any error about the array exceeding the preference. In some cases where you do not have enough memory to store two copies of the sparse array, you could end up with an "Out of memory" error that does not say anything about array size preferences.
But... as soon as you take the result of the calculation and do certain operations with it, you can run out of memory. For example if you use it in a \ (matrix left divide) or / (matrix right divide) operation, then the result of doing those operations on a sparse array is typically a dense array, and that could easily need more memory that your system has.
so my thought was this product will generate less significant digits; hence less memory will be used.
No, significant digits has no role in this matter, unless you are mixing single() and double(). class double() is always the same number of bits. For example, storing the number 1.5 does not use fewer bits than storing 3.729064039408867 does: when 1.5 is stored, all those extra bits are being stored as being precisely 0, like 1.500000000000000
Generally speaking, Symbolic Toolbox numbers are stored quite differently, and for those, additional digits does take extra storage...each group of roughly 9 digits at a time taking an extra 32 bits. However, Symbolic Toolbox objects can never be sparse()