I have the following piece of Matlab code, which calculates Mahalanobis distances between a vector and a matrix with several iterations. I am trying to find a faster method to do this by vectorization but without success.
S.data=0+(20-0).*rand(15000,3);
S.a=0+(20-0).*rand(2500,3);
S.resultat=ones(length(S.data),length(S.a))*nan;
S.b=ones(length(S.a),3,length(S.a))*nan;
for i=1:length(S.data)
for j=1:length(S.a)
S.a2=S.a;
S.a2(j,:)=S.data(i,:);
S.b(:,:,j)=S.a2;
if j==length(S.a)
for k=1:length(S.a);
S.resultat(i,k)=mahal(S.a(k,:),S.b(:,:,k));
end
end
end
end
I have now modified the code and avoid one of the loop. But it is still very long. If someone have an idea, I will be very greatful!
S.data=0+(20-0).*rand(15000,3);
S.a=0+(20-0).*rand(2500,3);
S.resultat=ones(length(S.data),length(S.a))*nan;
for i=1:length(S.data)
for j=1:length(S.a)
S.a2=S.a;
S.a2(j,:)=S.data(i,:);
S.resultat(i,j)=mahal(S.a(j,:),S.a2);
end
end
Introduction and solution code
You can replace the innermost loop that uses
mahal
with something that is a bit vectorized, as it uses some pre-calculated values (with the help ofbsxfun
) inside a loop-shortened and hacked version ofmahal
.Basically you have a
2D
array, let's call itA
for easy reference and a3D
array, let's call itB
. Let the output be stored be into a variableout
. So, the innermost code snippet could be extracted and based on the assumed variable names.Original loopy code
So, what I did was to hack into
mahal.m
and look for portions that could be vectorized when the inputs are2D
and3D
. Now,mahal
usesqr
inside it, which could not be vectorized. Thus, we end up with a hacked code.Hacked code
Now, to extend this hack solution to the problem code, one can introduce few more tweaks to pre-calculate more values being used those nested loops.
Final solution code
Benchmarking
Here's the benchmarking code to compare the proposed solution against the code listed in the problem -
Runtimes -
Thus, we might get around
2.7x
speedup with the proposed approach and some tweaks!