How to make loops run faster
1 回表示 (過去 30 日間)
古いコメントを表示
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 件のコメント
David Sanchez
2013 年 6 月 25 日
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);
採用された回答
その他の回答 (4 件)
Hugo
2013 年 6 月 26 日
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 件のコメント
Hugo
2013 年 6 月 26 日
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
2013 年 6 月 25 日
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 件のコメント
Dr. Seis
2013 年 6 月 25 日
編集済み: Dr. Seis
2013 年 6 月 25 日
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 件のコメント
Jan
2013 年 6 月 27 日
編集済み: Jan
2013 年 6 月 27 日
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.
参考
カテゴリ
Help Center および File Exchange で Matrix Indexing についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!