Undocumented Matlab
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT

Matrix processing performance

July 13, 2011 14 Comments

A few days ago, fellow Matlab blogger Roy Fahn, well-respected in the Israeli Matlab community, posted an interesting article on his MATLAB with Fun blog (note the word-play). Since his article is in Hebrew, and the automated Google Translation is somewhat lacking, I thought of sharing Roy’s post here (with his permission of course), for the minority of the Matlab community which is not fluent in Hebrew…

Roy’s translated post: “Anyone who adds, detracts (from execution time)”

In the story of Eve and the serpent, the first woman told the serpent about the prohibition of eating from the Tree of Knowledge, adding to that prohibition a ban on touching the tree (something that God has not commanded). The snake used this inaccuracy in her words, showing her that one can touch the tree without fear, and therefore argued that the prohibition to eat its fruit is similarly not true. As a result, Eve was tempted to eat the fruit, and the rest is known. Jewish sages said of the imaginary prohibition which Eve has added, that this is an example where “Anyone who adds, [in effect] detracts”.
Recently I [Roy] came across an interesting phenomenon, that in MATLAB, adding elements to a vector on which an action is performed, does not degrade the execution time, but rather the reverse. Adding vector elements actually reduces execution time!
Here’s an example. Try to rank the following tic-toc segments from fastest to slowest:

x = rand(1000,1000);
% Segment #1
y = ones(1000,1000);
tic
for i=1:100
    y = x .* y;
end
toc
% Segment #2
y=ones(1000,1000);
tic
for i=1:100
    y(:,1:999) = x(:,1:999) .* y(:,1:999);
end
toc
% Segment #3
y=ones(1000,1000);
tic
for i=1:100
    y(1:999,:) = x(1:999,:) .* y(1:999,:);
end
toc

x = rand(1000,1000); % Segment #1 y = ones(1000,1000); tic for i=1:100 y = x .* y; end toc % Segment #2 y=ones(1000,1000); tic for i=1:100 y(:,1:999) = x(:,1:999) .* y(:,1:999); end toc % Segment #3 y=ones(1000,1000); tic for i=1:100 y(1:999,:) = x(1:999,:) .* y(1:999,:); end toc

The first loop multiplies all the elements of the x and y matrices, and should therefore run longer than the other loops, which multiply matrices that are one row or one column smaller. However, in practice, the first loop was the fastest – just 0.25 seconds on my computer, whereas the second ran for 1.75 seconds, and the third – 6.65 seconds [YMMV].
Why is the first loop the fastest?
The subscription operation performed in each of the latter two loops is a wasteful action, and therefore in such cases I would suggest that you run your operation on the full matrix, and then get rid of the unnecessary row or column.
And why does the second loop run faster than the third?
This is related to the fact that MATLAB prefers operations on columns rather than rows. In the second loop, all the elements are multiplied except those in the last column, while in the third loop all the elements that have been extracted from all rows are multiplied, except for the last row.
In your work with MATLAB, have you encountered similar phenomena that are initially counter-intuitive, such as the example described above? If so, please post a comment below, or directly on Roy’s blog.
Is all of this undocumented? I really don’t know. But it is certainly unexpected and interesting…

Related posts:

  1. Undocumented view transformation matrix – Matlab's view function returns an undocumented output transformation matrix....
  2. Allocation performance take 2 – The clear function has some non-trivial effects on Matlab performance. ...
  3. Performance: scatter vs. line – In many circumstances, the line function can generate visually-identical plots as the scatter function, much faster...
  4. Convolution performance – Matlab's internal implementation of convolution can often be sped up significantly using the Convolution Theorem. ...
  5. Preallocation performance – Preallocation is a standard Matlab speedup technique. Still, it has several undocumented aspects. ...
  6. Array resizing performance – Several alternatives are explored for dynamic array growth performance in Matlab loops. ...
Performance Pure Matlab Undocumented feature
Print Print
« Previous
Next »
14 Responses
  1. Malcolm Lidierth July 13, 2011 at 10:47 Reply

    See also
    http://www.mathworks.com/company/newsletters/news_notes/june07/patterns.html

  2. Jonathan Birge July 13, 2011 at 11:53 Reply

    I think this is really more an indication of how poorly MATLAB is written, than anything else. It seems that if you do subscripts on the right hand side, instead of optimizing that out by simply truncating the iteration internally, MATLAB actually creates an entirely new copy. In fact, MATLAB is so poorly optimized that if you replace your first segment with

    y = x(:,1:1000) .* y(:,1:1000);

    you will find that it runs just as slow as the second segment.

    Given that the MathWorks essentially has a monopoly on scientific numerical analysis software, I’d say it’s not very surprising that the core language implementation is of such low quality. I will grant you this, though: the fact that MATLAB, despite being claimed to have an optimizing JIT compiler, does something so stupid as to make an entirely new copy of an array when you only want to read a subset of it is definitely something the MathWorks doesn’t want to document…

  3. Jonathan Birge July 14, 2011 at 07:40 Reply

    One thing to add: I originally thought maybe the problem was that the original example used in-place assignment, since y was on both sides. This isn’t the issue, and the results are the same (including a huge slowdown for replacing x with the “equivalent” x(:,1:1000)) if you use x for both variables on the right side.

  4. celine July 14, 2011 at 07:58 Reply

    In the same subject, the function squeeze can actually be slower than reshape. Example below

    %%% evaluate the timing of 'squeeze'
    % create 3D tables
    apple=10*rand([100,300,400],'single');
    maxLoop=100000;
     
    % pick one line and one column
    tic
    for i=1:maxLoop  %this will take 3s
        core=squeeze(apple(3,25,:));
    end
    toc
     
    tic
    for i=1:maxLoop     %this will take 0.3s
        core2=apple(3,25,:);
        core2=reshape(core2,[1,400]);
    end
    toc
     
    tic
    for i=1:maxLoop       %this will take 0.3s
        core3=apple(3,25,:);
        core3=reshape(core3,[400,1]);
    end
    toc

    %%% evaluate the timing of 'squeeze' % create 3D tables apple=10*rand([100,300,400],'single'); maxLoop=100000; % pick one line and one column tic for i=1:maxLoop %this will take 3s core=squeeze(apple(3,25,:)); end toc tic for i=1:maxLoop %this will take 0.3s core2=apple(3,25,:); core2=reshape(core2,[1,400]); end toc tic for i=1:maxLoop %this will take 0.3s core3=apple(3,25,:); core3=reshape(core3,[400,1]); end toc

  5. rami July 18, 2011 at 00:01 Reply

    The reason the second loop is faster than the third loop is that matlab uses Column-Major Order :

    a = [1,2,3;4,5,6]

    a = [1,2,3;4,5,6]

    is stored as 1,4,2,5,3,6.

    (Ref : http://en.wikipedia.org/wiki/Row-major_order#Column-major_order)

    As for the first one being faster than the second one, I dont know.

    Cheers

  6. Ajay Iyer July 19, 2011 at 09:46 Reply

    Interestingly, here is a segment of code (#4) that is as fast as the #1.

    % Segment #4
    y=ones(1000,1000);
    tic
    x = x(:);
    y = y(:);
    for i=1:100
        y = x.*y ;
    end
    y = reshape(y,1000,1000);
    x = reshape(x,1000,1000);
    toc

    % Segment #4 y=ones(1000,1000); tic x = x(:); y = y(:); for i=1:100 y = x.*y ; end y = reshape(y,1000,1000); x = reshape(x,1000,1000); toc

  7. Thomas M. July 19, 2011 at 10:22 Reply

    A little outside the subject, but I’ve been developing code using Simulink for xPC Target and the bottleneck in my algorithm is the large matrix calculation of A = M*N, where both M and N are (250,250). I am sampling at 0.001 and I am trying to find ways to optimize the speed. Is it possible to make this calculation faster? Also, why would this calculation take longer with xPC 5.0 compared with xPC 4.3 loaded on the same system?

    • Yair Altman July 19, 2011 at 11:50 Reply

      @Thomas – You can always use a GPU or MEX to speed up the calculations, but try to think whether you really need to have all this data. Just reducing the size to (100,100) will improve performance by 2 orders of magnitude, not to mention reducing memory problems, thrashing (memory swaps) etc.

    • Thomas M. July 25, 2011 at 09:27 Reply

      The matrix has to be that size. How can the GPU be leveraged on xPC Target? Also, what do you mean by using MEX to speed up calculations?

  8. Waiting for asynchronous events | Undocumented Matlab July 18, 2012 at 11:51 Reply

    […] Performance tuning can indeed be counter-intuitive sometimes, until you learn the underlying reasons when it becomes clear (I’ve shown several examples of this in the past) […]

  9. Peter Gardman April 4, 2013 at 10:13 Reply

    Dear Yair,
    I’m wondering about the fastest way of creating a structure. In my ignorance, I used to think that >>A.B = x would call A = struct(‘B’,x) so writing A = struct(‘B’,x) in an mfile would be much faster. To my surprise A.B =x is much faster:

    >> tic, A.B = 3; toc
    Elapsed time is 0.000003 seconds.

    >> tic, M = struct(‘B’,3); toc
    Elapsed time is 0.000297 seconds.

    Do you have any clue why is this?, or, if you have already talked about this in a post, could you please indicate it to me where? Thank you very much

    • Yair Altman April 4, 2013 at 16:44 Reply

      @Peter – I suspect that this is due to the fact that A.B is directly interpreted by the Matlab interpreter, whereas struct(…) goes through a library routine (in libmx.dll on Windows).

      Note: when you place the profiled code in an m-file, rather then testing in the non-optimized Command Prompt, the speedup is only ~2 or 3, not 100 (not that a x2 speedup should be disparaged…).

      In a related matter, I compare alternatives for preallocating arrays of structs here.

      • Peter Gardman April 5, 2013 at 10:48

        Thank you very much Yair

  10. Python:Performance of row vs column operations in NumPy – IT Sprite November 5, 2015 at 05:09 Reply

    […] are a few articles that show that MATLAB prefers column operations than row operations, and that depending on you lay […]

Leave a Reply
HTML tags such as <b> or <i> are accepted.
Wrap code fragments inside <pre lang="matlab"> tags, like this:
<pre lang="matlab">
a = magic(3);
disp(sum(a))
</pre>
I reserve the right to edit/delete comments (read the site policies).
Not all comments will be answered. You can always email me (altmany at gmail) for private consulting.

Click here to cancel reply.

Useful links
  •  Email Yair Altman
  •  Subscribe to new posts (email)
  •  Subscribe to new posts (feed)
  •  Subscribe to new posts (reader)
  •  Subscribe to comments (feed)
 
Accelerating MATLAB Performance book
Recent Posts

Speeding-up builtin Matlab functions – part 3

Improving graphics interactivity

Interesting Matlab puzzle – analysis

Interesting Matlab puzzle

Undocumented plot marker types

Matlab toolstrip – part 9 (popup figures)

Matlab toolstrip – part 8 (galleries)

Matlab toolstrip – part 7 (selection controls)

Matlab toolstrip – part 6 (complex controls)

Matlab toolstrip – part 5 (icons)

Matlab toolstrip – part 4 (control customization)

Reverting axes controls in figure toolbar

Matlab toolstrip – part 3 (basic customization)

Matlab toolstrip – part 2 (ToolGroup App)

Matlab toolstrip – part 1

Categories
  • Desktop (45)
  • Figure window (59)
  • Guest bloggers (65)
  • GUI (165)
  • Handle graphics (84)
  • Hidden property (42)
  • Icons (15)
  • Java (174)
  • Listeners (22)
  • Memory (16)
  • Mex (13)
  • Presumed future risk (394)
    • High risk of breaking in future versions (100)
    • Low risk of breaking in future versions (160)
    • Medium risk of breaking in future versions (136)
  • Public presentation (6)
  • Semi-documented feature (10)
  • Semi-documented function (35)
  • Stock Matlab function (140)
  • Toolbox (10)
  • UI controls (52)
  • Uncategorized (13)
  • Undocumented feature (217)
  • Undocumented function (37)
Tags
ActiveX (6) AppDesigner (9) Callbacks (31) Compiler (10) Desktop (38) Donn Shull (10) Editor (8) Figure (19) FindJObj (27) GUI (141) GUIDE (8) Handle graphics (78) HG2 (34) Hidden property (51) HTML (26) Icons (9) Internal component (39) Java (178) JavaFrame (20) JIDE (19) JMI (8) Listener (17) Malcolm Lidierth (8) MCOS (11) Memory (13) Menubar (9) Mex (14) Optical illusion (11) Performance (78) Profiler (9) Pure Matlab (187) schema (7) schema.class (8) schema.prop (18) Semi-documented feature (6) Semi-documented function (33) Toolbar (14) Toolstrip (13) uicontrol (37) uifigure (8) UIInspect (12) uitools (20) Undocumented feature (187) Undocumented function (37) Undocumented property (20)
Recent Comments
  • Iñigo (2 days 15 hours ago): Thanks Yair. I didn’t realize it was posted just above. It would be great to know about a solution soon
  • Yair Altman (3 days 22 hours ago): @Iñigo – your query is related to Seth’s question above. We can access the currently-browsed URL in JavaScript (for example: jBrowserPanel.executeScript...
  • Iñigo (5 days 14 hours ago): I am looking for setting a UI that allows following process: opening a web site, navigate inside this web site and at some specific moments (i.e. when the figure is closed or a button...
  • Nicholas (12 days 20 hours ago): Yair, this works wonderfully! I can’t thank you enough!
  • Collin (14 days 23 hours ago): Seth Good point, I am using 2022b, mathworks seems to have started using CEF browsers from 2019a, best I can tell. take a look at the package com.mathworks.toolbox.matla...
  • Seth (15 days 15 hours ago): Collin, What version of MATLAB are you using?
  • Collin (20 days 22 hours ago): Seth, I have had some success executing javascript that requires no return value by executing it directly (sort of) on the org.cef.browser.CefBrowser that a...
  • Coo Coo (22 days 17 hours ago): FFT-based convolution is circular whereas MATLAB’s conv functions have several options (‘valid’, ‘same’, ‘full’) but unfortunately not...
  • Seth (22 days 20 hours ago): No luck with removing the space.
  • Seth (22 days 21 hours ago): The javascript code works fine running the application from the 2019b desktop version and the 2016b deployed version.
  • Seth (22 days 21 hours ago): I have been using this browser functionality in 2016b because it works fully in deployed applications in that version. However, because of Java 7 being flagged as a security risk, I...
  • Yair Altman (22 days 21 hours ago): I’ve never tested javascript callbacks, but perhaps you should try removing the extra space after the “matlab:” protocol specifier. Does it make any difference?
  • Seth (22 days 22 hours ago): I have been using this functionality in 2016b since it works in deployed applications and have not had a reason to need to upgrade but with java 7 being flagged as a security risk I am...
  • KEVIN (42 days 23 hours ago): I apologize, I intended my response to fall under ‘T’ but did not seem to work. I was referring to the bit of code posted by ‘T’ regarding the toolgroup and...
  • Yair Altman (42 days 23 hours ago): It is not clear from your comment which code exactly you are referring to and what you see differently in 19b vs. 20b, so I cannot assist with your specific query. In general I...
Contact us
Undocumented Matlab © 2009 - Yair Altman
This website and Octahedron Ltd. are not affiliated with The MathWorks Inc.; MATLAB® is a registered trademark of The MathWorks Inc.
Scroll to top