Help vectorize for loop please

2 views (last 30 days)
Emad
Emad on 11 Mar 2011
I want to get rid of that for loop and just use/vectors/matrices, so i can optimize my code. if any one can help thanks.
%help compute the average
d = max(size(x));
c = 1/(d-1);
function y1 = f1(r)
y1 = tanh((1-r)*7) +.7;
end
%y2 will be returned
y2 = zeros(d,1);
z1 = x(1:2:2*N - 1);
z2 = x(2:2:2*N );
for j=1:(d/2)
Z1 = z1(j) - z1; %x - xj
Z2 = z2(j) - z2; %y - yj
Z3 = (Z2.*Z2) + (Z1.*Z1); %(x-xj)^2 + (y - yj)^2
Z3 = sqrt(Z3);%|X- Xj|
Z3(j) = 1;
Z1 = Z3.\Z1;% (x - xj)/|X - Xj|
Z2 = Z3.\Z2;% (y - yj)/|X - Xj|
Z4 = f1(Z3); % F( |X - Xj|)
Z1 = Z1.*Z4;%F( |X - Xj|)*(x - xj)/|X - Xj|
Z2 = Z2.*Z4;%F( |X - Xj|)*(y - yj)/|X - Xj|
y2(2*j - 1) = c*sum(Z1);
y2(2*j) = c*sum(Z2);
end

Accepted Answer

Matt Tearle
Matt Tearle on 12 Mar 2011
As far as I can tell, this seems to replace your code and is a tiny bit faster. (I tested only on small arrays, so maybe the savings will be significant on an actual problem). I assume that N = d/2? I'm also assuming that x is a column vector. I was using x = randi(10,20,1) to test, and I got the same answers as your code.
d = length(x);
c = 1/(d-1);
f1 = @(r) tanh((1-r)*7) +.7;
z1 = x(1:2:2*N - 1);
z2 = x(2:2:2*N );
y2 = zeros(d,1);
Z1 = bsxfun(@minus,z1',repmat(z1,1,d/2));
Z2 = bsxfun(@minus,z2',repmat(z2,1,d/2));
Z3 = sqrt((Z2.*Z2) + (Z1.*Z1));
Z3(1:((d/2)+1):end)=1;
Z1 = Z1./Z3;
Z2 = Z2./Z3;
Z4 = f1(Z3);
Z1 = Z1.*Z4;
Z2 = Z2.*Z4;
y2(1:2:2*N - 1) = sum(Z1)*c;
y2(2:2:2*N) = sum(Z2)*c;
  4 Comments
Jan
Jan on 12 Mar 2011
As far as I remember the version >= 6.5 (R13) use the JIT acceleration.
Matt Tearle
Matt Tearle on 13 Mar 2011
But, like everything in MATLAB, it's being continually improved, so, generally, the later the version, the better the JIT benefits.

Sign in to comment.

More Answers (1)

Matt Tearle
Matt Tearle on 11 Mar 2011
You don't need a loop at all -- all your statements inside the loop will work as vectorized statements with virtually no modification.
Just get rid of the subscripts on the first two lines.
Delete the line Z3(j) = 1; I don't know what you were hoping this did, but I doubt it was what it actually does. Before that line, Z3 is a scalar. Then if j is 1, it just overwrites Z3. For any other j, it will make Z3 a vector of j elements. The first will be whatever Z3 was from the previous line, the last will be 1, and everything in the middle will be 0. Is that what you intended? Maybe it is, given the use of sum(Z1) later, but it's a very strange algorithm.
Finally, use indexing like you did to extract z1 and z2 from x to get the results into y2.
  3 Comments
Matt Tearle
Matt Tearle on 12 Mar 2011
Oops, my bad. I misread your code (all those z1s and Z2s and y2s...!) OK. Ignore everything I said. New answer coming right now.
Matt Tearle
Matt Tearle on 12 Mar 2011
BTW "I know matlab works much better with vectors then loops" is not necessarily true any more (depends on which version). Thanks to the JIT optimization, loops are now pretty quick. There are cases where you can tie yourself in knots trying to vectorize only to *lose* performance. In this case, I think you can get a bit of speed-up (see my new answer) by using matrices.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!