Help vectorize for loop please

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

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

cut performance time in half, thanks I appreciate it
which version of matlab has JIT optimization?
As far as I remember the version >= 6.5 (R13) use the JIT acceleration.
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

The loop is necessary at the moment. Z3 is a vector. when I do Z3(j) = 1, that sets the jth element to 1 so in the next line when i do Z1 = Z3.\Z1, I will not divide by zero.irregardless of all of that. I am trying to convert the loop into a vectorized statement, since I know matlab works much better with vectors then loops for example:
if x is a vector of n elements I can find the sum by
sumofx = 0;
for i=1:n
sumofx = sumofx + x(i);
end
or I can do sumofx = sum(x);
and this computes it much more efficiently.
so I am trying to convert my loop into a vector statemnt, I know it will be difficult but i know it is possible.
Oops, my bad. I misread your code (all those z1s and Z2s and y2s...!) OK. Ignore everything I said. New answer coming right now.
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.

Asked:

on 11 Mar 2011

Community Treasure Hunt

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

Start Hunting!