elegant threading

User Forumelegant threading
Chuck asked 3 years ago

Hi, Jason,

I've decided to take you up on your offer to look at some of my code to help me make the threading more elegant.  As it stands, the snippet I'm attaching below doesn't work because it writes to globals inside the threads.  I can see one solution which is to turn all the global structure elements that I write to into locals then update the structures outside of the proc.  This though is not a very elegant solution and seems to run contrary to the whole idea of using structures in the first place.

Thanks for your help,


To begin, this is the set of threaded calls to one of the procs:

 threadStat {cXiVX1,cXiVw1,p0,d1,pr} = reg_parms(thrd_idx[1],(thrd_idx[4]-1),p0, d0, d1, pr);
 threadStat {cXiVX2,cXiVw2,p0,d1,pr} = reg_parms(thrd_idx[2],(thrd_idx[3]-1),p0, d0, d1, pr);
 threadStat {cXiVX3,cXiVw3,p0,d1,pr} = reg_parms(thrd_idx[3],(thrd_idx[4]-1),p0, d0, d1, pr);

cXiVX = cXiVX1+cXiVX2+cXiVX3;
cXiVw = cXiVw1+cXiVw2+cXiVw3;

 And here is the proc.  I highlighted in RED all the gloabal structure write statements:

proc(5) = reg_parms(_strt,_end,struct parameter p0, struct data0 d0, struct data1 d1, struct prob pr);
 local _cXiVX,_cXiVw,imz,imz2,imzj,i,j,ij,ci,ci3,i1,i2,D_i,cZiVZ,cZiVw,Zmat,ZiVZ,ZiVw,icZiVZ,cicZiVZ,bi_hat;
 local bnd,l_bnd,rnd,Xmat,XiVX,XiVw,U01;
 _cXiVX = zeros(XODcol,XODcol);
 _cXiVw = zeros(XODcol,1);
 bnd = zeros(2,1);
 l_bnd = zeros(2,1);
 rnd = zeros(2,1);
 for i (_strt,_end,1);
  // start calculations for bi_sp1[z,.]
  if cust_chg[i] == 1;
   ci = cust_id[i];
   D_i = d1.Dfull[imz2-1:imz2,.];
   cZiVZ = zeros(2,2);
   cZiVw = zeros(2,1);
   for j (0,c_cnt[ci]-1,1);
    ij = i+j;
    if d0.DAP_only[ij] == 1;
     {i1} = offer(pr.CumOP_O);
     pr.OD_drw[ij] = pr.iOD_fee[i1];
     pr.DAP_drw[ij] = dap_fees[ij];
     Zmat = ((pr.iOD_fee[i1]/d1.deposits[ij])~0)|(0~d1.dap_dep[ij])|(pr.iOD_fee[i1]/(d1.deposits[ij])~d1.dap_dep[ij]);
     d1.Zfull[imzj-2:imzj,.] = Zmat;
    elseif d0.OD_only[ij] == 1;
     {i1} = offer(pr.CumOP_D);
     pr.OD_drw[ij] = od_fees[ij];
     pr.DAP_drw[ij] = pr.iDAP_fee[i1];
     Zmat = (d1.od_dep[ij]~0)|(0~(pr.iDAP_fee[i1]/d1.deposits[ij]))|(d1.od_dep[ij]~(pr.iDAP_fee[i1]/d1.deposits[ij]));
     d1.Zfull[imzj-2:imzj,.] = Zmat;
    elseif d0.ODDAP[ij] == 1;
     pr.OD_drw[ij] = od_fees[ij];
     pr.DAP_drw[ij] = dap_fees[ij];
     Zmat = d1.Zfull[imzj-2:imzj,.];
    elseif d0.DAP_only[ij] == 0 and d0.OD_only[ij] == 0 and d0.ODDAP[ij] == 0;
     {i1} = offer(pr.CumOP_O);
     {i2} = offer(pr.CumOP_D);
     pr.OD_drw[ij] = pr.iOD_fee[i1];
     pr.DAP_drw[ij] = pr.iDAP_fee[i2];
     Zmat = ((pr.iOD_fee[i1]/d1.deposits[ij])~0)|(0~(pr.iDAP_fee[i2]/d1.deposits[ij]))|
     d1.Zfull[imzj-2:imzj,.] = Zmat;
    ZiVZ = Zmat'p0.iV_sp1*Zmat;
    ZiVw = Zmat'p0.iV_sp1*(d0.w_sp1[imzj-2:imzj] - d1.Xfull[imzj-2:imzj,.]*p0.b_sp1 - p0.Cap_xi[ci3-2:ci3]);
    cZiVZ = cZiVZ + ZiVZ;
    cZiVw = cZiVw + ZiVw;
    if j == c_cnt[ci]-1;
     icZiVZ = invpd(cZiVZ + p0.iH_sp1);
     bi_hat = icZiVZ*(cZiVw + p0.iH_sp1*D_i*p0.thet_sp1);
     cicZiVZ = chol(icZiVZ)';

     // GHK Simulator
     {U01,seedu} = rndlcu(2,1,seedu);
     bnd[1] = -bi_hat[1]/cicZiVZ[1,1];
     l_bnd[1] = (-5 - bi_hat[1])/cicZiVZ[1,1];
     rnd[1] = cdfni(U01[1]*(cdfn(bnd[1]) - cdfn(l_bnd[1])) + cdfn(l_bnd[1]));
     bnd[2] = (-bi_hat[2] - cicZiVZ[2,1]*rnd[1])/cicZiVZ[2,2];
     l_bnd[2] = (-5 - bi_hat[2] - cicZiVZ[2,1]*rnd[1])/cicZiVZ[2,2];
     rnd[2] = cdfni(U01[2]*(cdfn(bnd[2]) - cdfn(l_bnd[2])) + cdfn(l_bnd[2]));
     p0.bi_sp1[ci,.] = (bi_hat + cicZiVZ*rnd)';
  d1.Zbi[imz-2:imz] = d1.Zfull[imz-2:imz,.]*p0.bi_sp1[ci,.]';
  d1.Cap_xi[imz-2:imz] = p0.Cap_xi[ci3-2:ci3];
  // end calculations for bi_sp1[ci,.]
  Xmat = d1.Xfull[imz-2:imz,.];
  XiVX = Xmat'p0.iV_sp1*Xmat;
  XiVw = Xmat'p0.iV_sp1*(d0.w_sp1[imz-2:imz] - d1.Zbi[imz-2:imz] - p0.Cap_xi[ci3-2:ci3]);
  _cXiVX = _cXiVX + XiVX;
  _cXiVw = _cXiVw + XiVw;
 endfor; // i loop 
1 Answers
jjones Staff answered 3 years ago

I am wondering about a few things. In the code you return 3 global structures, d1, p0 and pr.

For simplicity, let's just focus on 'p0' for now. Your procedure makes only one assignment to this structure on line 82:

p0.bi_sp1[ci,.] = (bi_hat + cicZiVZ*rnd)';

This member is used on line 86:

d1.Zbi[imz-2:imz] = d1.Zfull[imz-2:imz,.]*p0.bi_sp1[ci,.]';

but not again in the code that I have. Is this something you will want to access after your threadset? If so, I think this is a problem, because you may get the p0 structure that is returned from any of the three threads.

If you do not need to access p0.bi_sp1 later in the program, then I would remove it from the retp statement and that problem will be solved. Let me know if any or all of the updated structure members such as p0.bi_sp1 need to be accessed later by this program and we can find a better solution.