× {{alert.msg}} Never ask again
Get notified about new tutorials RECEIVE NEW TUTORIALS

MATLAB spending an incredible amount of time writing a relatively small matrix

Ray Phan
Jul 09, 2015
<p>Your call to <code>zeros</code> is incorrect. Looking at your code, <code>D</code> looks like a <code>D x 2</code> array. However, your call of <code>s = max(D,1)</code> would actually generate another <code>D x 2</code> array. By consulting the documentation for <a href="http://www.mathworks.com/help/matlab/ref/max.html" rel="nofollow"><code>max</code></a>, this is what happens when you call <code>max</code> in the way you used:</p> <blockquote> <p><code>C = max(A,B)</code> returns an array the same size as <code>A</code> and <code>B</code> with the largest elements taken from <code>A</code> or <code>B</code>. Either the dimensions of <code>A</code> and <code>B</code> are the same, or one can be a scalar.</p> </blockquote> <p>Therefore, because you used <code>max(D,1)</code>, you are essentially comparing every value in <code>D</code> with the value of 1, so what you're actually getting is just a copy of <code>D</code> in the end. Using this as input into <code>zeros</code> has rather undefined behaviour. What will actually happen is that for each row of <code>s</code>, it will allocate a temporary <code>zeros</code> matrix of that size and toss the temporary result. Only the dimensions of the last row of <code>s</code> is what is recorded. Because you have a very large matrix <code>D</code>, this is probably why the profiler hangs here at 100% utilization. Therefore, each parameter to <code>zeros</code> must be <strong>scalar</strong>, yet your call to produce <code>s</code> would produce a <strong>matrix</strong>. </p> <p>What I believe you intended should have been:</p> <pre><code>s = max(D(:)); </code></pre> <p>This finds the overall maximum of the matrix <code>D</code> by unrolling <code>D</code> into a single vector and finding the overall maximum. If you do this, your code should run faster.</p> <p>As a side note, this post may interest you:</p> <p><a href="http://stackoverflow.com/questions/14169222/faster-way-to-initialize-arrays-via-empty-matrix-multiplication-matlab">Faster way to initialize arrays via empty matrix multiplication? (Matlab)</a></p> <p>It was shown in this post that doing <code>zeros(n,n)</code> is in fact slow and there are several neat tricks to initializing an array of zeros. One way is to accomplish this by empty matrix multiplication:</p> <pre><code>data = zeros(n,0)*zeros(0,n); </code></pre> <p>One of my personal favourites is that if you assume that <code>data</code> was <strong>not declared / initialized</strong>, you can do:</p> <pre><code>data(n,n) = 0; </code></pre> <hr> <p>If I can also comment, that <code>for</code> loop is quite inefficient. What you are doing is calculating a 2D histogram / accumulation of data. You can replace that <code>for</code> loop with a more efficient <a href="http://www.mathworks.com/help/matlab/ref/accumarray.html" rel="nofollow"><code>accumarray</code></a> call. This also avoids allocating an array of <code>zeros</code> and <code>accumarray</code> will do that under the hood for you.</p> <p>As such, your code would basically become this:</p> <pre><code>function [data] = DataHandler(D) data = accumarray([D(:,1) D(:,2)+1], 1); </code></pre> <p><code>accumarray</code> in this case will take all pairs of row and column coordinates, stored in <code>D(i,1)</code> and <code>D(i,2) + 1</code> for <code>i = 1, 2, ..., size(D,1)</code> and place all that match the same row and column coordinates into a separate 2D bin, we then add up all of the occurrences and the output at this 2D bin gives you the total tally of how many values at this 2D bin which corresponds to the row and column coordinate of interest mapped to this location.</p> <p>This tip was originally posted on <a href="http://stackoverflow.com/questions/31175948/MATLAB%20spending%20an%20incredible%20amount%20of%20time%20writing%20a%20relatively%20small%20matrix/31176145">Stack Overflow</a>.</p>

Get New Tutorials Delivered to Your Inbox

New tutorials will be sent to your Inbox once a week.

comments powered by Disqus