Parfor sucessfully implemented in Dynare

Dear Community,

I’ve recently implemented a parallelized version of the stoch_simul.m in order to speed up my computations. As mentioned in this thread, the main obstacle was the use of global variables; I’ve modified many of the original Dynare functions (such as set_random_seed) slightly so that they are passed local versions of M_, oo_, etc. My initial runs show very significant speedups if I run with the 4 cores on my CPU. Are any of you guys interested in this code? If so, I will clean up the files post them.

Best,
Zhao

Hi Zhao,

I’ve been struggling with this precise problem. I’m simply trying to parallelize stoch_simul on a cluster for different parameterization.

Any help/hint would be greatly appreicated!

Example codes please.

Here it is. Any tips would be helpful! Thank you!
Loop_dynare.mod (4.9 KB)
Loop_main.m (1.15 KB)

Ok. I will try to walk you through this, but I need you to do some changes for me.

  1. The function allcomb is missing
  2. I need a clean mod-file without all the loop part. Please provide a mod-file that has the correct starting values for all parameters hard-coded and runs the desired simulations.
  3. Please provide a description of the targets. That is, when you write X(5,ii) = oo_.mean(10);, please provide me with a comment showing the name of the variable you are looking for. Variable 10 for example seems to be welfare.
  4. Please replace

ppsipi = X(1,ii); ppsiy = X(2,ii); rrhor = X(3,ii); ppibar = X(4,ii);
by set_param_value statements like

set_param_value('ppsiy',start_value)
where start_value is the value for the first loop step.
5. Please get rid of all parameter dependencies defined before the model block. If you have an analytic steady state, please use a steady_state_model block.

Thank you!

Here are the fixes…As you see, I’m looping over 4 coefficients and would like to run some big grids on parallel.
Loop_main.m (1.79 KB)
Loop_dynare.mod (4 KB)
allcomb.m (4.21 KB)

I’m still struggling with this. Any tips or hints on how to implement this…?

This is somewhat more involved. First, you have to alter the dynare functions stoch_simul.m and disp_th_moments.m. For the latter, change the header to

function oo_=disp_th_moments(dr,var_list,M_,options_,oo_)

(note that for some reasons the underscores are not displayed; just follow the already existing statements and variable definitions) and delete the

global M_ oo_ options_
In stoch_simul.m change the call to

            disp_th_moments(oo_.dr,var_list);

to

oo_=disp_th_moments(oo_.dr,var_list_,M_,options_,oo_);
Upon doing this, you should be able to use the attached code.
Loop_parfor.zip (4.56 KB)

Thank you for your help! Made a couple of fixes and it seems to be working.

Changed the parfor loop to [a,b]=wrapper_function(X_in(:,ii),M_,options_,oo_,var_list_); X_out(:,ii)=[a;b];

Two questions though,

  1. It doesn’t seem like stoch_simul needs to be altered. Since the loop calls resol.m directly and stoch_simul is only called in the first run, the original stoch_simul file seems to work.
  2. the moments that return from the exercise are slightly off in decimal points compared to running a standalone mod-file once. Is this expected?

Thanks!

  1. The change to stoch_simul is needed to not break Dynare when executing it standalone. If you alter disp_th_moments in the describe way, you need to adapt Dynare to the new syntax.
  2. No, this is not to be expected and may indicate there is something wrong. If you did not fix 1), this may be the reason.

I’ve changed the stoch_simul as you suggested and it’s giving the same results that are slightly off.

What’s weird is that the non-parallel loop I initially had is giving the same results as this parallelized version. It’s the stand-alone that I run to check that is slightly off of these two…

Please provide code and instructions to replicate the issue.

I tried to run the files contained in Loop_parfor.zip, however, ran into a few problems. I’m using Matlab R2017a and Dynare 4.5.1 on a Mac.

First, I think in newer Dynare versions I don’t have to change anything in stoch_simul.m and disp_th_moments.m anymore, as they already contain the lines which jpfeifer proposed to change, is that correct?

Then, if I just execute Loop_main.m, I get the following warning and error message

Starting parallel pool (parpool) using the ‘local’ profile …
connected to 2 workers.
Warning: Element(s) of class ‘dates’ do not match the current constructor definition. The element(s) have been converted to structures.

In parallel.internal.pool.deserialize (line 9)
In parallel.internal.pool.deserializeFunction (line 12)
In remoteParallelFunction (line 33)
Warning: Element(s) of class ‘dates’ do not match the current constructor definition. The element(s) have been converted to structures.
In parallel.internal.pool.deserialize (line 9)
In parallel.internal.pool.deserializeFunction (line 12)
In remoteParallelFunction (line 33)

Error using wrapper_function (line 10)
Field assignment to a non-structure array object.

Error in Loop_main (line 58)
parfor ii = 2:size(X,2)

If I do what hakeru7 proposed, i.e.,

Matlab tells me that it doesn’t know X_in. I tried to define X_in the same way as X_out, i.e.,

X_in=zeros(2,size(X,2));

I get the following error message

Error using wrapper_function (line 6)
Index exceeds matrix dimensions.

Error in Loop_main (line 59)
parfor ii = 2:size(X,2)

Maybe there is an easy fix to this problem. I guess I just have to get the dimensions of X_in right? Has anyone worked with the parfor code recently and can help me with this?

  1. It is indeed correct that we got rid of the global variables in that function.
  2. I was able to run the attached version in Matlab R2017a with Dynare 4.5.3
    Loop_parfor.zip (4.6 KB)

Thank you very much! This code works fine. I only found it more convenient to write

parfor ii = 2:size(X,2)
X_out(1,ii)=wrapper_function(X(:,ii),M_,options_,oo_,var_list_);
end

because then the position of welfare in X_out coincides with the position of the respective parameter vector in X.
Or, in case you are interested in both output variables of the wrapper_function

parfor ii = 2:size(X,2)
[a,b]=wrapper_function(X(:,ii),M_,options_,oo_,var_list_);
X_out1(ii)=a;
X_out2(ii)=b;
end

X_out=[X_out1; X_out2];