How do I speed up a loop where I need to check whether elements are less than 0
Show older comments
I am trying to speed-up the following loop. This loop updates a value function v_d given a guess v_ini_exp. All variables are pre-allocated. From running a profiler it seems that the major bottleneck is the line where I need to discard elements of a matrix which are less than 0. In my model, these values are not feasible. But it seems that this is taking almost 65% of the execution time. I was wondering if there is a way to speed up the loop (provided below)
I can think of two ways to try to speed it up:
(1) Speed-up the line that takes over 65% of the execution time (I tried different formulation but the current one is the fastest I could think of)
(2) Try to vectorize at least one the the loop, but this is unclear to me since the variable d in the inner loop is a matrix.
Is there any way to speed up this loop? I can use parfor to decrease the runtime by around 50% but is there another way to speed up this loop before jumping to use parallel toolbox?
% Variables defined up to this loop:
% (1) q_ini is an array (z_grid_num-by-k_grid_num-by-b_grid_num)
% (2) v_ini_exp is an array (z_grid_num-by-k_grid_num-by-b_grid_num)
% (3) wealth is an array (z_grid_num-by-k_grid_num-by-b_grid_num)
% (4) choice a matrix (k_grid_num-by-b_grid_num)
% continuation value function
for ii = 1:z_grid_num
q_ini_ii = squeeze(q_ini(ii,:,:));
v_ini_exp_ii = squeeze(v_ini_exp(ii,:,:));
choice = q_ini_ii.*b_grid_choice - k_grid_choice;
for jj = 1:k_grid_num
for kk = 1:b_grid_num
% dividends at time t
d = wealth(ii,jj,kk) + choice;
% choosing optimal consumption
vec_d = (d + v_ini_exp_ii).*(d>0) + (-1e30).*(d<=0); % <- THIS LINE TAKES 65% OF THE EXECUTION TIME
[v_d(ii,jj,kk)] = max(vec_d,[],'all'); % <- THIS LINE TAKES 25% OF THE EXECUTION TIME
end
end
end
10 Comments
Ameer Hamza
on 18 Mar 2020
I am a bit confused by your code. Why do you need this line?
vec_d = (d + v_ini_exp_ii).*(d>0) + (-1e30).*(d<=0);
which is replacing all the values less than 0 with -1e30.
However, you are using max() function, which will select the maximum value anyway. So why replace those values with -1e30.
Walter Roberson
on 18 Mar 2020
You replace exact 0 with a small negative value. If it is acceptable to instead replace negative with 0 then use max(0,expression)
Michal Szkup
on 18 Mar 2020
Walter Roberson
on 18 Mar 2020
vec_d = max(0, d + v_ini_exp_ii)
would probably be faster if it is acceptable to use 0 instead of 1e-30
Ameer Hamza
on 18 Mar 2020
I guess that issue here is that the OP only wants the maximum value of this sum when d > 0. I think the OP's current solution is probably the fastest it can get in MATLAB.
Adam Danz
on 18 Mar 2020
vec_d = (d + v_ini_exp_ii).*(d>0)
is the way to go, then.
Walter Roberson
on 18 Mar 2020
max((d + v_ini_exp_ii).*(d>0))
does appear to be about as fast as you are likely to get, being only a small bit slower than max(d+v_ini_exp_ii) in my tests.
Walter Roberson
on 18 Mar 2020
Michal, is one of the following a real possibility ?
- v_ini_exp_ii can be quite large in a situation where d is negative -- large enough that d plus the value could end up being the maximum overall ?
- v_ini_exp_ii can be consistently enough negative where d are positive such that the maximum of the sum where d is positive could be negative ?
Michal Szkup
on 18 Mar 2020
Edited: Michal Szkup
on 18 Mar 2020
Michal Szkup
on 18 Mar 2020
Edited: Michal Szkup
on 18 Mar 2020
Answers (0)
Categories
Find more on Loops and Conditional Statements in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!