# How to make loops run faster

2 views (last 30 days)

Show older comments

I have a 3d cashflow matrix, which have number of prices simulations as the first dimension, days left in a contract as the second dimension and opportunities left in the contract as the third dimension. I want to sum the cashflows per price simulation over the days left in the contract and the opportunities left, and then I want to discount the cashflows. I have written the code for it:

for j=days_left_in_contract-1:-1:2,

counter=days_left_in_contract-j;

if days_left_in_contract-j<days_left_with_opportunities,

difference=days_left_in_contract-j;

else

difference=days_left_with_opportunities;

end

for w=1:difference,

i=1:1:counter;

interest_rate_vector=exp(-interest_rate*i);

k=1;

for i=1:simulations,

if Eon_pris_t(i,j)>Gaspris_t(i,j), % Two different price simulations

Y(k,1)=sum(cashflow(i,j+1:j+counter,w).*interest_rate_vector);

k=k+1;

end % close if

end % close i

end % close w

end % close j

However, the code runs very slowly when the number of prices simulations is over 1000. Do any of you guys know how to make the code run faster?

Thank you very much in advance.

##### 1 Comment

David Sanchez
on 25 Jun 2013

In your code you have:

counter=days_left_in_contract-j;

Y(k,1)=sum(cashflow(i,j+1:j+counter,w).*interest_rate_vector);

Did you realize that if

counter=days_left_in_contract-j;

then

j+counter == days_left_in_contract

and you could save an operation by writing

Y(k,1)=sum(cashflow(i,j+1:days_left_in_contract,w).*interest_rate_vector);

### Accepted Answer

### More Answers (4)

Hugo
on 26 Jun 2013

Try this

for j=days_left_in_contract-1:-1:2,

counter=days_left_in_contract-j;

difference=min(counter,days_left_with_opportunities);

i=1:1:counter;

interest_rate_vector=exp(-interest_rate*i);

for w=1:difference,

Y(:,1)=sum(cashflow(Eon_pris_t(:,j)>Gaspris_t(:,j),j+1:j+counter,w)*interest_rate_vector);

end

end

end

The most important change is that I've moved the lines

i=1:1:counter;

interest_rate_vector=exp(-interest_rate*i);

outside the for loop. The values of this vectors are not initialize in each for loop actually, so they can be moved safely.

I have done other changes to make the code shorter and to save some for loops. matlab prefers things in matrix form.

By the way, the error that you mentioned before should occur in your original code as well. The error occurs in the line

Y(k,1)=sum(cashflow(i,j+1:j+counter,w).*interest_rate_vector);

and it occurs because sum(...) gives you a number while interest_rate_vector is a vector, and therefore cannot be multiplied using .*. In the code I wrote, this is replaced by *. Anyway, there is still the problem that you are trying to save a vector in Y(k,1), which is only one element, and that cannot be done. So you should check that the your code is right or clarify what Y really is (perhaps a cell array or so).

##### 2 Comments

Hugo
on 26 Jun 2013

Ok, please correct me if I'm wrong, but in the first line of code you wrote, I see two parentesis opening and three closing, therefore that should be an error.

Nevertheless, as you said, in your original code the things are right. My mistake.

With respect to the first error, yes, now I see, please replace * with ".*". With the corrections, it should read like this:

for j=days_left_in_contract-1:-1:2,

counter=days_left_in_contract-j;

difference=min(counter,days_left_with_opportunities);

i=1:1:counter;

interest_rate_vector=exp(-interest_rate*i);

for w=1:difference,

Y(:,1)=sum(cashflow(Eon_pris_t(:,j)>Gaspris_t(:,j),j+1:j+counter,w).*interest_rate_vector);

end

end

end

About moving

i=1:1:counter; interest_rate_vector=exp(-interest_rate*i);

above the

for w=1:...

I don't know what the problem could be, since it does not depend on w in any way. Can it be that the error comes from another thing? Try to move it before any other modification.

David Sanchez
on 25 Jun 2013

##### 0 Comments

Dr. Seis
on 25 Jun 2013

Edited: Dr. Seis
on 25 Jun 2013

Could have something to do with pre-allocation of Y

There are more elegant ways to do this (I am sure), but if the below modifications do not cause a noticeable decrease in your current runtime then we will need to look at other things:

for j=days_left_in_contract-1:-1:2

counter=days_left_in_contract-j;

if days_left_in_contract-j<days_left_with_opportunities

difference=days_left_in_contract-j;

else

difference=days_left_with_opportunities;

end

for w=1:difference

interest_rate_vector=exp(-interest_rate*(1:counter));

% Get indices that contribute to Y

idx = zeros(simulations,1);

for i=1:simulations

if Eon_pris_t(i,j)>Gaspris_t(i,j)

idx(i) = i;

end % close if

end % close i

% Populate Y

idx=idx(idx>0));

Y = zeros(numel(idx),1);

k=1;

for i = idx

Y(k)=sum(cashflow(i,j+1:j+counter,w).*interest_rate_vector);

k=k+1;

end

end % close w

end % close j

Are you planning on keeping the results in Y for later calculations? Right now Y is overwritten after each step in w

##### 0 Comments

Jan
on 27 Jun 2013

Edited: Jan
on 27 Jun 2013

Y = zeros(numel(idx), 1);

for j = days_left_in_contract-1:-1:2

counter = days_left_in_contract - j;

interest_rate_vector = exp(-interest_rate:-1:-interest_rate * counter));

interest_rate_vector = interest_rate_vector.'; % Column vector

difference = min(counter,days_left_with_opportunities);

for w = 1:difference

% Get indices that contribute to Y

idx = Eon_pris_t(:, j) > Gaspris_t(:, j); % Logical index

% Populate Y

Y(:) = 0; % Reset values

for k = 1:numel(idx)

if idx(k)

Y(k) = cashflow(k, j+1:j+counter, w) * interest_rate_vector;

end

end

... now hyou need to use the values of Y here, because they are

... overwritten in the next iteration

end % close w

end % close j

The DOT product is usually faster than the sum of the elementwise multiplication.

### See Also

### Categories

### Community Treasure Hunt

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

Start Hunting!