Note that there are some explanatory texts on larger screens.

plurals
  1. POFaster way to initialize arrays via empty matrix multiplication? (Matlab)
    primarykey
    data
    text
    <p>I've stumbled upon the weird way (in my view) that Matlab is dealing with <a href="http://www.mathworks.com/help/matlab/math/empty-matrices-scalars-and-vectors.html" rel="noreferrer">empty matrices</a>. For example, if two empty matrices are multiplied the result is:</p> <pre><code>zeros(3,0)*zeros(0,3) ans = 0 0 0 0 0 0 0 0 0 </code></pre> <p>Now, this already took me by surprise, however, a quick search got me to the link above, and I got an explanation of the somewhat twisted logic of why this is happening. </p> <p><strong>However</strong>, nothing prepared me for the following observation. I asked myself, how efficient is this type of multiplication vs just using <code>zeros(n)</code> function, say for the purpose of initialization? I've used <a href="http://www.mathworks.com/matlabcentral/fileexchange/18798" rel="noreferrer"><code>timeit</code></a> to answer this:</p> <pre><code>f=@() zeros(1000) timeit(f) ans = 0.0033 </code></pre> <p>vs:</p> <pre><code>g=@() zeros(1000,0)*zeros(0,1000) timeit(g) ans = 9.2048e-06 </code></pre> <p>Both have the same outcome of 1000x1000 matrix of zeros of class <code>double</code>, but the empty matrix multiplication one is ~350 times faster! (a similar result happens using <code>tic</code> and <code>toc</code> and a loop)</p> <p>How can this be? are <code>timeit</code> or <code>tic,toc</code> bluffing or have I found a faster way to initialize matrices? (this was done with matlab 2012a, on a win7-64 machine, intel-i5 650 3.2Ghz...)</p> <p><strong>EDIT:</strong></p> <p>After reading your feedback, I have looked more carefully into this peculiarity, and tested on 2 different computers (same matlab ver though 2012a) a code that examine the run time vs the size of matrix n. This is what I get:</p> <p><img src="https://i.stack.imgur.com/DSZn7.png" alt="enter image description here"></p> <p>The code to generate this used <code>timeit</code> as before, but a loop with <code>tic</code> and <code>toc</code> will look the same. So, for small sizes, <code>zeros(n)</code> is comparable. However, around <code>n=400</code> there is a jump in performance for the empty matrix multiplication. The code I've used to generate that plot was:</p> <pre><code>n=unique(round(logspace(0,4,200))); for k=1:length(n) f=@() zeros(n(k)); t1(k)=timeit(f); g=@() zeros(n(k),0)*zeros(0,n(k)); t2(k)=timeit(g); end loglog(n,t1,'b',n,t2,'r'); legend('zeros(n)','zeros(n,0)*zeros(0,n)',2); xlabel('matrix size (n)'); ylabel('time [sec]'); </code></pre> <p>Are any of you experience this too?</p> <p><strong>EDIT #2:</strong></p> <p>Incidentally, empty matrix multiplication is not needed to get this effect. One can simply do:</p> <pre><code>z(n,n)=0; </code></pre> <p>where n> some threshold matrix size seen in the previous graph, and get the <strong>exact</strong> efficiency profile as with empty matrix multiplication (again using timeit). </p> <p><img src="https://i.stack.imgur.com/EZVOI.png" alt="enter image description here"></p> <p>Here's an example where it improves efficiency of a code:</p> <pre><code>n = 1e4; clear z1 tic z1 = zeros( n ); for cc = 1 : n z1(:,cc)=cc; end toc % Elapsed time is 0.445780 seconds. %% clear z0 tic z0 = zeros(n,0)*zeros(0,n); for cc = 1 : n z0(:,cc)=cc; end toc % Elapsed time is 0.297953 seconds. </code></pre> <p>However, using <code>z(n,n)=0;</code> instead yields similar results to the <code>zeros(n)</code> case.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload