Help vectorize for loop please

7 次查看(过去 30 天)
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

采纳的回答

Matt Tearle
Matt Tearle 2011-3-12
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 个评论
Jan
Jan 2011-3-12
As far as I remember the version >= 6.5 (R13) use the JIT acceleration.
Matt Tearle
Matt Tearle 2011-3-13
But, like everything in MATLAB, it's being continually improved, so, generally, the later the version, the better the JIT benefits.

请先登录,再进行评论。

更多回答(1 个)

Matt Tearle
Matt Tearle 2011-3-11
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 个评论
Matt Tearle
Matt Tearle 2011-3-12
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 2011-3-12
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.

请先登录,再进行评论。

Community Treasure Hunt

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

Start Hunting!

Translated by