The results can be a little misleading. When you multiply two empty matrices, the resulting matrix is ​​not immediately "distributed" and "initialized", rather it is delayed until you use it first (sort of like a lazy estimate).
The same applies to indexing outside of a grow variable, which in the case of numeric arrays fills any missing entries with zeros (I will then discuss the non-numeric case). Of course, matrix growth in this way does not overwrite existing elements.
This way, although it might seem faster, you just delay the distribution time until you actually start using the matrix. In the end you will have similar timings, as if you made a selection from the very beginning.
An example to show this behavior, compared to several other alternatives :
N = 1000; clear z tic, z = zeros(N,N); toc tic, z = z + 1; toc assert(isequal(z,ones(N))) clear z tic, z = zeros(N,0)*zeros(0,N); toc tic, z = z + 1; toc assert(isequal(z,ones(N))) clear z tic, z(N,N) = 0; toc tic, z = z + 1; toc assert(isequal(z,ones(N))) clear z tic, z = full(spalloc(N,N,0)); toc tic, z = z + 1; toc assert(isequal(z,ones(N))) clear z tic, z(1:N,1:N) = 0; toc tic, z = z + 1; toc assert(isequal(z,ones(N))) clear z val = 0; tic, z = val(ones(N)); toc tic, z = z + 1; toc assert(isequal(z,ones(N))) clear z tic, z = repmat(0, [NN]); toc tic, z = z + 1; toc assert(isequal(z,ones(N)))
The result shows that if you summarize the elapsed time for both teams in each case, you will get similar general timings:
// zeros(N,N) Elapsed time is 0.004525 seconds. Elapsed time is 0.000792 seconds. // zeros(N,0)*zeros(0,N) Elapsed time is 0.000052 seconds. Elapsed time is 0.004365 seconds. // z(N,N) = 0 Elapsed time is 0.000053 seconds. Elapsed time is 0.004119 seconds.
Other timings:
// full(spalloc(N,N,0)) Elapsed time is 0.001463 seconds. Elapsed time is 0.003751 seconds. // z(1:N,1:N) = 0 Elapsed time is 0.006820 seconds. Elapsed time is 0.000647 seconds. // val(ones(N)) Elapsed time is 0.034880 seconds. Elapsed time is 0.000911 seconds. // repmat(0, [NN]) Elapsed time is 0.001320 seconds. Elapsed time is 0.003749 seconds.
These measurements are too small in milliseconds and may not be very accurate, so you can run these commands several thousand times in a loop and take an average value. Also, sometimes the execution of stored M-functions is faster than running scripts or the command line, as certain optimizations only happen this way ...
In any case, the selection is usually performed once, so who needs it, if an additional 30 ms is required :)
Similar behavior can be observed with arrays of cells or arrays of structures. Consider the following example:
N = 1000; tic, a = cell(N,N); toc tic, b = repmat({[]}, [N,N]); toc tic, c{N,N} = []; toc
which gives:
Elapsed time is 0.001245 seconds. Elapsed time is 0.040698 seconds. Elapsed time is 0.004846 seconds.
Please note that even if they are all equal, they occupy a different amount of memory:
>> assert(isequal(a,b,c)) >> whos abc Name Size Bytes Class Attributes a 1000x1000 8000000 cell b 1000x1000 112000000 cell c 1000x1000 8000104 cell
Actually, the situation here is a little more complicated, since MATLAB probably shares the same empty matrix for all cells, rather than creating multiple copies.
The array of cells a is actually an array of uninitialized cells (an array of NULL pointers), and b is an array of cells, where each cell is an empty array [] (inside and due to data sharing, only the first cell b{1} points to [] , and everyone else has a link to the first cell). The final array c is similar to a (uninitialized cells), but with the last one containing an empty numeric matrix [] .
I looked at the list of exported C functions from libmx.dll (using the Dependency Walker tool ), and I found some interesting things.
There are undocumented functions for creating uninitialized arrays: mxCreateUninitDoubleMatrix , mxCreateUninitNumericArray and mxCreateUninitNumericMatrix . In fact, there is an idea of File Exchange using these functions to provide a faster alternative to the zeros function.
There is an undocumented function called mxFastZeros . Googling online, I can see that you cross-asked this question on MATLAB Answers, as well as excellent answers there. James Turs (the same author of UNINIT from earlier) gave an example on how to use this undocumented function.
libmx.dll is associated with the tbbmalloc.dll shared library. This is a scalable Intel TBB memory allocator . This library provides equivalent memory allocation functions ( malloc , calloc , free ), optimized for parallel applications. Remember that many MATLAB functions are automatically multithreaded , so I won’t be surprised if zeros(..) multithreaded and uses the Intel memory allocator as soon as the matrix size is large enough (here is a recent comment by Loren Shure that confirms this fact).
Regarding the last point about the memory allocator, you can write a similar test in C / C ++, similar to what was @PavanYalamanchili , and compare the available allocators. Something like this . Remember that MEX files have slightly higher memory management overhead because MATLAB automatically frees up any memory that was allocated in MEX files using the mxCalloc , mxMalloc or mxRealloc . For what it was worth, in older versions it was previously possible to change the internal memory manager .
EDIT:
Here is a more thorough criterion for comparing the alternatives discussed. It specifically shows that as soon as you emphasize the use of the entire selected matrix, all three methods are on an equal footing, and the difference is negligible.
function compare_zeros_init() iter = 100; for N = 512.*(1:8) % ZEROS(N,N) t = zeros(iter,3); for i=1:iter clear z tic, z = zeros(N,N); t(i,1) = toc; tic, z(:) = 9; t(i,2) = toc; tic, z = z + 1; t(i,3) = toc; end fprintf('N = %4d, ZEROS = %.9f\n', N, mean(sum(t,2))) % z(N,N)=0 t = zeros(iter,3); for i=1:iter clear z tic, z(N,N) = 0; t(i,1) = toc; tic, z(:) = 9; t(i,2) = toc; tic, z = z + 1; t(i,3) = toc; end fprintf('N = %4d, GROW = %.9f\n', N, mean(sum(t,2))) % ZEROS(N,0)*ZEROS(0,N) t = zeros(iter,3); for i=1:iter clear z tic, z = zeros(N,0)*zeros(0,N); t(i,1) = toc; tic, z(:) = 9; t(i,2) = toc; tic, z = z + 1; t(i,3) = toc; end fprintf('N = %4d, MULT = %.9f\n\n', N, mean(sum(t,2))) end end
Below are time intervals averaged over 100 iterations in terms of increasing the size of the matrix. I performed tests in R2013a.
>> compare_zeros_init N = 512, ZEROS = 0.001560168 N = 512, GROW = 0.001479991 N = 512, MULT = 0.001457031 N = 1024, ZEROS = 0.005744873 N = 1024, GROW = 0.005352638 N = 1024, MULT = 0.005359236 N = 1536, ZEROS = 0.011950846 N = 1536, GROW = 0.009051589 N = 1536, MULT = 0.008418878 N = 2048, ZEROS = 0.012154002 N = 2048, GROW = 0.010996315 N = 2048, MULT = 0.011002169 N = 2560, ZEROS = 0.017940950 N = 2560, GROW = 0.017641046 N = 2560, MULT = 0.017640323 N = 3072, ZEROS = 0.025657999 N = 3072, GROW = 0.025836506 N = 3072, MULT = 0.051533432 N = 3584, ZEROS = 0.074739924 N = 3584, GROW = 0.070486857 N = 3584, MULT = 0.072822335 N = 4096, ZEROS = 0.098791732 N = 4096, GROW = 0.095849788 N = 4096, MULT = 0.102148452