Improving MATLAB Array Efficiency

Join the discussion
Registration is free. Ask a follow-up in this thread, or start your own.
1 reply · 4K views
Meurig
Messages
6
Reaction score
0
Hi all,

I have the following code:

M = zeros(N)
for i = 1:N
for j = 1:N
M(i,j)= log(norm(rs(:,i)-rc(:,j)))+log(norm(ri(:,i)-rc(:,j)));
end
end

Where rs, rc and ri are 2xN arrays.

Is there a way to construct the matrix without the use of the two for loops?
I'm trying to reduce the time cost of my code.

Thanks,
Meurig

UPDATE:

Have rewritten as:
[rsx,rcx] = meshgrid(rs(1,:),rc(1,:)');
[rsy,rcy] = meshgrid(rs(2,:),rc(2,:)');
M1 = (rsx-rcx).^2;
M2 = (rsy-rcy).^2;
[rix,rcx] = meshgrid(ri(1,:),rc(1,:)');
[riy,rcy] = meshgrid(ri(2,:),rc(2,:)');
M3 = (rix-rcx).^2;
M4 = (riy-rcy).^2;
Ms = log((M1+M2).^(1/2));
Mi = log((M3+M4).^(1/2));
M = Ms+Mi;

Reducing the time cost by 99%.

If anyone has a nicer way of writing this I'd be very interested though!
Cheers,
Meurig
 
Last edited:
Physics news on Phys.org
Quick note: your first and second version of the code have transposed results.

You can take advantage of Matlab's ability to work with matrices of N>2 dimensions. Reshape the matrices so that the rows are in the 3rd dimension, then repmat like you did (meshgrid is really just repmat done twice), and finally sum along dim=3. That way you don't need to “manually” deal with rows 1 and 2. And the code is no longer limited to 2xN matrices. If you later need to work with more than 2 rows, you don't have to change the code at all.

I used a function called sumsq to handle the squaring (makes it more readable, sumsq(x, N)=sum(x.*x, N)) and took out the square root out of the log:

Code:
[nr, nc]=size(rs);

rss=repmat(reshape(rs', 1, nc, nr), [nc 1 1]);
rii=repmat(reshape(ri', 1, nc, nr), [nc 1 1]);
rcc=repmat(reshape(rc', nc, 1, nr), [1 nc 1]);

M=(log(sumsq(rss-rcc, 3))+log(sumsq(rii-rcc, 3)))/2;
M=M';  % If you want M to look like the for-loop version