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
Your problems could lay on the Eon_pris_t(i,j) Gaspris_t(i,j) functions: The calling itself takes its time, although it should not be what slows your code. What do these functions exactly do?
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
Find more on Matrix Indexing in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!