From your code, you have recognized that the dist
matrix is symmetric
dist(i,j) = norm(cord(:,i)-cord(:,j));
dist(j,i) = dist(i,j);
You could change the inner loop to account for this and reduce by roughly one half the number of calculations needed
for j = i:size(cord,2)
Further, we can avoid the dist(j,i) = dist(i,j);
at each iteration and just do that at the end by extracting the upper triangle part of dist
and adding its transpose to the dist
matrix to account for the symmetry
dist = zeros(size(cord,2),size(cord,2));
for i = 1:size(cord,2)
for j = i:size(cord,2)
dist(i,j) = norm(cord(:,i)-cord(:,j));
end
end
dist = dist + triu(dist)';
The above addition is fine since the main diagonal is all zeros.
It still performs poorly though and so we should take advantage of vectorization. We can do that as follows against the inner loop
dist = zeros(size(cord,2),size(cord,2));
for i = 1:size(cord,2)
dist(i,i+1:end) = sum((repmat(cord(:,i),1,size(cord,2)-i)-cord(:,i+1:end)).^2);
end
dist = dist + triu(dist)';
dist = sqrt(dist);
For every element in cord
we need to calculate its distance with all other elements that follow it. We reproduce the element with repmat
so that we can subtract it from every element that follows without the need for the loop. The differences are squared and summed and assigned to the dist
matrix. We take care of the symmetry and then take the square root of the matrix to complete the norm
operation.
With tic
and toc
, the original distance calculation with a random cord (cord = rand(3,num);
) took ~93 seconds. This version took ~2.8.