Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unexpected slowdown of function that modifies array in-place

This bug is due to Matlab being too smart for its own good.

I have something like

for k=1:N
    stats = subfun(E,k,stats);
end

where statsis a 1xNarray, N=5000 say, and subfun calculates stats(k)from E, and fills it into stats

function stats = subfun(E,k,stats)
    s = mean(E);
    stats(k) = s;
end

Of course, there is some overhead in passing a large array back and forth, only to fill in one of its elements. In my case, however, the overhead is negligable, and I prefer this code instead of

for k=1:N
    s = subfun(E,k);
    stats(k) = s;
end

My preference is because I actually have a lot more assignments than just stats. Also some of the assignments are actually a good deal more complicated.

As mentioned, the overhead is negligable. But, if I do something trivial, like this inconsequential if-statement

for k=1:N
    i = k;
    if i>=1
        stats = subfun(E,i,stats);
    end
end

the assignments that take place inside subfun then suddenly takes "forever" (it increases much faster than linearly with N). And it's the assignment, not the calculation that takes forever. In fact, it is even worse than the following nonsensical subfun

function stats = subfun(E,k,stats)
    s = calculation_on_E(E);
    clear stats
    stats(k) = s;
end

which requires re-allocation of stats every time.

Does anybody have the faintest idea why this happens?

like image 966
Patrick Avatar asked Sep 26 '13 18:09

Patrick


1 Answers

This might be due to some obscure detail of Matlab's JIT. The JIT of recent versions of Matlab knows not to create a new array, but to do modifications in-place in some limited cases. One of the requirements is that the function is defined as

function x = modify_big_matrix(x, i, j)
x(i, j) = 123;

and not as

function x_out = modify_big_matrix(x_in, i, j)
x_out = x_in;
x_out(i, j) = 123;

Your examples seem to follow this rule, so, as Praetorian mentioned, your if statement might prevent the JIT from recognizing that it is an in-place operation.

If you really need to speed up your algorithm, it is possible to modify arrays in-place using your own mex-functions. I have successfully used this trick to gain a factor of 4 speedup on some medium sized arrays (order 100x100x100 IIRC). This is however not recommended, could segfault Matlab if you are not careful and might stop working in future versions.

like image 167
Bas Swinckels Avatar answered Nov 19 '22 09:11

Bas Swinckels