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
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…