Speed of matrix storage

1 view (last 30 days)
Philipp Metsch on 14 Apr 2017
Answered: Philip Borghesani on 17 Apr 2017
If I have a matrix
A=[A11 A12; A21 A22]
why is it faster in Matlab to store it like
A=A11*[1 0; 0 0] + A12*[0 1; 0 0] + A21*[0 0; 1 0] + A22*[0 0; 0 1];?
Philipp Metsch on 15 Apr 2017
Yes, all components of A are scalars. I timed the code using tic and toc in a for loop to test not only one execution, but 1e6.

Philip Borghesani on 17 Apr 2017
Analyzing a snippet of code out of context has little value and often leads to improper conclusions. In this code creating a new matrix takes the majority of the time. I believe that the matrix operation is doing a better job of reusing the existing variable that is going out of scope. When attempting to find the fastest way to do something don't try to break it down line by line, look at a useful block of code and think about how to make that faster.
The fastest way to do this by far is with direct indexing and to reuse the matrix but that may not be representative of the final requirements:
A_11=4;
A_12=6;
A_21=7;
A_22=17;
loops=1e6;
tic;
for i=1:loops
A3(2,2)=A_22;A3(2,1)=A_21;A3(1,2)=A_12;A3(1,1)=A_11;
% A3=[];
end
toc;
If the comment on the line A3=[] is removed and similar lines are added to the other loops then direct assignment seems to be half way between concatenation and the matrix operations.
The version of MATLAB used for testing this also make a significant difference. Micro optimizing based on the results of a command line or script test with one version of matlab is a particularly bad idea.

dpb on 14 Apr 2017
Edited: dpb on 15 Apr 2017
I can't reproduce the result...
metch.m
tic,B=[A A;A A];t1=toc;
tic,B=A*[1 0; 0 0] + A*[0 1; 0 0] + A*[0 0; 1 0] + A*[0 0; 0 1];t2=toc;
>> N=100;
>> t=zeros(N,2);
>> for i=1:N,metch,t(i,:)=[t1 t2];end
>> [mean(t);std(t)]
ans =
1.0e-04 *
0.2349 0.2365
0.1026 0.0276
>> mean(t)
ans =
1.0e-04 *
0.2349 0.2365
>> (ans(2)/ans(1)-1)*100
ans =
0.6959
>>
While it's small (<1% difference on average), the second is longer than the first.
>> sum(t(:,2)<t(:,1))
ans =
1
>>
Only one case where the first didn't win...
What can't try here that may be the problem/cause might be the automatic singleton expansion in lastest revisions??? The above code only works without if the A are 2x2; I think the expansion would run for any compatible sizes maybe??? If that were the case, I'd not be surprised at all.

Philipp Metsch on 15 Apr 2017
Edited: per isakson on 15 Apr 2017
In my case the code looks like this:
A_11=4;
A_12=6;
A_21=7;
A_22=17;
tic;
for i=1:1e6;
A1=[A_11 A_12; A_21 A_22];
end;
toc;
tic;
for i=1:1e6;
A2=A_11*[1 0; 0 0] + A_12*[0 1; 0 0] + A_21*[0 0; 1 0] + A_22*[0 0; 0 1];
end;
toc;
The result of tic/toc gives "Elapsed time is 1.697598 seconds." for the first loop and "Elapsed time is 0.098466 seconds." for the second loop. If I run the code with profiler on, the result is qualitatively the same.
I think this difference is quite dramatic, but I am not able to figure out where it comes from.
per isakson on 15 Apr 2017
Only The MathWorks knows!
The loop is kind of meaningless. A1 and A2 are overwritten a million times. Replacing them by A=zeros(2,2,N); gives a different result.