How to vectorize for loops

2 次查看(过去 30 天)
Evangelos Mitsokapas
回答: Jan 2018-2-4
Hello, I am quite new to Matlab but I have typed down the following piece of code. It works as desired, but I have noticed the following:
  • Matlab spends a lot of time on exprnd(.). Is there a way to improve this flaw?
  • As it is quite visible I am using three 'for' loops but I know that Matlab is much more efficient when loops are vectorized. Is there any way you could help me achieve this?
%Random Walk
RW=10;
nsteps = 10;
X = -99999:99999;
L = length(X);
m = ['x','d','*','s','o','.','h','^','v','>','<','p','h'];
S1 = zeros(nsteps,1);
MSD1 = zeros(nsteps,1);
nstepss1 = zeros(nsteps,1);
for k=1:nsteps+1
K1 = zeros(RW,1);
V1 = zeros(RW,1);
for j=1:RW+1
position = 0;
Xright = 0;
Xleft = 0;
u_left = 0;
u_right = 0;
for i=1:nsteps+1
u = exprnd( 1 );
z = rand;
p = 0.1*(u_right)./(0.3)./0.2*(u_right)./(0.3)+0.1*(u_left)./(0.3)).*(k<(1/20)*nsteps) + 0.1*(u_right)./(3.0)./0.2*(u_right)./(3.0)+0.1*(u_left)./(3.0)).*(k>=(1/20)*nsteps);
left_step = -1.*(z<p);
right_step = 1.*(z>p);
n = left_step+right_step;
%Boundary Conditions
if position+n > X(L)
position = X(1);
elseif position+n < X(1)
position = X(L);
else
position = position+n;
end
% Choice of Step
if n == 1
Xright = Xright+1;
if u_right>=u
u_right = u_right;
else
u_right=u;
end
else
Xleft = Xleft+1;
if u_left>=u
u_left = u_left;
else
u_left=u;
end
end
end
K1(j) = position; %Final position of each RW
V1(j) = ((Xright-Xleft)/nsteps); %Average velocity of each RW
end
S1(k) = std(V1);
MSD1(k)=sqrt(S1(k)^2+(mean(V1))^2);
nstepss1(k) = k;
hold all;
PLO1 = scatter(nstepss1.', MSD1, '+');
end
hold off;
drawnow
Sorry for the long piece of code provided and thank you for your answers.
  3 个评论
Evangelos Mitsokapas
Hello, thanks for taking the time to answer. Would you mind elaborating a little bit on what exactly you are suggesting? Like I mentioned in the beginning of the post, I am not yet quite familiar with the vectorizing concept.
Eric
Eric 2018-2-2
What foboo means is doing
myexprnd = exprnd(1,[nsteps+1, RW+1, nsteps+1]);
before the first for loop to get all the random numbers at once, since doing it that way is faster. Later, you can retrieve the number by calling
u = myexprnd(k,j,i);

请先登录,再进行评论。

回答(1 个)

Jan
Jan 2018-2-4
@Evangelos: Omit useless code like: u_right = u_right; This is a waste of time only and confusing. Better replace
if u_left>=u
u_left = u_left;
else
u_left=u;
end
by
u_left = min(u_lect, u);
Your code contains a bug the line:
p = 0.1*(u_right)./(0.3)./0.2*(u_right)./(0.3)+0.1*(u_left)./(0.3)) ...
There is a right parenthesis too much. After fixing this, this line should be cleaned massively: No parentheses around scalar numbers, (0.3)./0.2 is 1.5, etc.
Replace:
left_step = -1.*(z<p);
right_step = 1.*(z>p);
by
left_step = -(z<p);
right_step = (z>p);
and
if position+n > X(L)
position = X(1);
elseif position+n < X(1)
position = X(L);
else
position = position+n;
end
by:
position = position + n;
if position > X(L)
position = X(1);
elseif position < X(1)
position = X(L);
end
You can improve the code and accelerate it, but I do not think that it is a candidate for a vectorization.

类别

Help CenterFile Exchange 中查找有关 Graphics Object Programming 的更多信息

产品

Community Treasure Hunt

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

Start Hunting!

Translated by