ADMB Documentation  11.1.1646
 All Classes Files Functions Variables Typedefs Friends Defines
adcomm1.cpp
Go to the documentation of this file.
00001 /*
00002  * $Id: adcomm1.cpp 1112 2013-07-12 21:41:41Z johnoel $
00003  *
00004  * Author: David Fournier
00005  * Copyright (c) 2008-2012 Regents of the University of California
00006  */
00011 #if defined(USE_ADPVM)
00012 #include "adpvm2.h"
00013 
00014 //adstring ad_comm::subdir;
00015 
00016   // dvar_vector get_x_from_master(void)
00017   // {
00018   //   dvar_vector x;
00019   //   int ptid=pvm_parent();
00020   //   // ***************  begin variable receive block *********************
00021   //   adpvm_slave_vrecv(ptid);
00022   //   adpvm_unpack(x);
00023   //   adpvm_slave_end_vreceive();
00024   //   // ***************  end receive block ***********************************
00025   //   return x;
00026   // }
00027   //
00028   //
00029   // void send_f_to_master(const dvariable& f)
00030   // {
00031   //   // ***************  begin send block ***********************************
00032   //   int ptid=pvm_parent();
00033   //   adpvm_slave_vinitsend(PvmDataDefault);/* allocate message buffer */
00034   //   adpvm_pack(f);
00035   //   adpvm_slave_vsend(ptid);/* send buffer to master */
00036   //   // ***************  end send block ***********************************
00037   // }
00038   //
00039 int adpvm_slave_args::get_num_args(void){return num_args;}
00040 
00045 void ad_comm::get_slave_assignments(void)
00046 {
00047   // default slave assignment function
00048   // starts 1 slave on each host
00049   int nhost=pvm_manager->nhost;
00050   ivector & num_per_host=pvm_manager->num_per_host;
00051   if (allocated(num_per_host))
00052   {
00053     num_per_host.deallocate();
00054   }
00055   num_per_host.allocate(1,nhost);
00056   int i;
00057   pvm_manager->num_slave_processes=0;
00058   for (i=1;i<=nhost;i++)
00059   {
00060     int speed=pvm_manager->hostp[i-1].hi_speed;
00061     int nsprocs=speed%10;
00062     if (i>1) nsprocs+=1;
00063     cout << nsprocs << endl;
00064     num_per_host(i)=nsprocs;
00065     pvm_manager->num_slave_processes+=nsprocs;
00066   }
00067   imatrix & slave_assignments=pvm_manager->slave_assignments;
00068   if (allocated(slave_assignments))
00069   {
00070     slave_assignments.deallocate();
00071   }
00072   slave_assignments.allocate(1,nhost,1,num_per_host);
00073 
00074   slave_assignments.fill_seqadd(1,1);
00075 }
00076 
00081 void adpvm_slave_args::operator -- (void)
00082 {
00083   if (counter>0)
00084   {
00085     if (argv[counter])
00086     {
00087       delete [] argv[counter];
00088       argv[counter]=NULL;
00089     }
00090     counter--;
00091     strcpy(argv[0],(char*)str(counter));
00092   }
00093 }
00094 
00099 adpvm_slave_args::operator char ** ()
00100 {
00101   return argv;
00102 }
00103 
00108 void strcpy(const adpvm_slave_args& _a,const char * s)
00109 {
00110   adpvm_slave_args& a=(adpvm_slave_args&) _a;
00111   if (((char**)(a))[a.counter])
00112   {
00113     delete [] (((char**)(a))[a.counter]);
00114   }
00115   int len=strlen(s);
00116   if (len>1000) len=1000;
00117   ((char**)(a))[a.counter] = new char[len+1];
00118   if (a.counter>=a.get_num_args()-1)
00119   {
00120     cerr << "need to increase the number of slave args" <<endl;
00121     ad_exit(1);
00122   }
00123   strncpy(((char**)(a))[a.counter++],s,len+1);
00124   strcpy(((char**)(a))[0],(char*)str(a.counter));
00125 }
00126 
00131 void send_int_to_slaves(const ivector &  x)
00132 {
00133   // *********  begin constant send block  *************
00134   int sz=x.size();
00135   if (sz != ad_comm::pvm_manager->num_slave_processes)
00136   {
00137     cerr << "wrong shape for ivector in send_int_to_slaves" << endl;
00138     ad_exit(1);
00139   }
00140 
00141   int ii=x.indexmin();
00142   for (int i=1; i<=ad_comm::pvm_manager-> nhost; i++)
00143   {
00144     if (allocated(ad_comm::pvm_manager->slave_assignments(i)))
00145     {
00146       for (int j=ad_comm::pvm_manager->slave_assignments(i).indexmin();
00147                j<=ad_comm::pvm_manager->slave_assignments(i).indexmax();j++)
00148       {
00149         int bufid = adpvm_master_cinitsend( PvmDataRaw );
00150         adpvm_pack(x(ii++));
00151         adpvm_master_csend(ad_comm::pvm_manager->id(i,j));
00152       }
00153     }
00154   }
00155   // *********  end constant send block  *************
00156 }
00157 #endif
00158 #if defined(USE_ADPVM2)
00159 
00164 adpvm_manager::adpvm_manager(int _mode)
00165 {
00166   cout << "calling load library" << endl;
00167   if (load_adpvm_library() < 0)
00168   {
00169     cerr << "error loading pvm library" << endl;
00170     exit(1);
00171   }
00172   pvm_setopt(PvmRoute, PvmRouteDirect);  /* channel for communication */
00173   /* get and display configuration of the parallel machine */
00174   int status=pvm_config( &nhost, &narch, &hostp );  /* get configuration */
00175   if (status<0)
00176   {
00177     cerr << "error trying to get configuration of pvm (virtual machine)" << endl;
00178     if (status == PvmSysErr)
00179       cerr << " PVM Daemon not responing -- maybe it is not started" << endl;
00180     ad_exit(1);
00181   }
00182   printf("I found the following hosts in your virtual machine\n");
00183   int i;
00184   for (i = 0; i < nhost; i++)
00185   {
00186     printf("    %s\n", hostp[i].hi_name);
00187   }
00188   //id.allocate(0,nhost);
00189   mode=_mode;
00190   if (mode == 1)  // master
00191   {
00192     slave_argv = new adpvm_slave_args(20,20);
00193     strcpy(*slave_argv,"progname");
00194     int on1,nopt1;
00195     if ( (on1=option_match(ad_comm::argc,ad_comm::argv,"-exec",nopt1))>-1)
00196     {
00197       if (nopt1 !=1 && nopt1 !=2)
00198       {
00199         cerr << "Wrong number of options to -exec -- must be 1"
00200           " you have " << nopt1 << endl;
00201         ad_exit(1);
00202       }
00203       slave_names+= ad_comm::argv[on1+1];
00204       slave_names+= "-exec";
00205       slave_names+= ad_comm::argv[on1+2];
00206     }
00207     else
00208     {
00209       slave_names+="test";
00210     }
00211   }
00212   if (!ptm)
00213   {
00214     ptm = new adtimer;
00215   }
00216 }
00217 
00222 char * adpvm_slave_args::operator () (int i)
00223 {
00224   if (i>=num_args || i<0)
00225   {
00226     cerr << "index value of " << i
00227          << "is out of bounds in adpvm_slave_args"
00228          << " maximum value is " << num_args-1
00229          << " minimum value is 0 " << endl;
00230     ad_exit(1);
00231   }
00232   return argv[i];
00233 }
00234 typedef char * charptr;
00235 
00240 adpvm_slave_args::adpvm_slave_args(int _num_args,int _length_args)
00241 {
00242   //char ** argv;
00243   counter=1;
00244   num_args=_num_args;
00245   if (allocated(length_args))
00246     length_args.deallocate();
00247   length_args.allocate(0,num_args-1);
00248   length_args=_length_args;
00249   argv = new charptr[num_args+1];
00250   argv[0] = new char[20];
00251   for (int i = 1; i < num_args; i++)
00252   {
00253     argv[i] = NULL;
00254   }
00255   argv[num_args]=NULL;
00256 }
00257 
00262 adpvm_slave_args::~adpvm_slave_args()
00263 {
00264   if (argv)
00265   {
00266     for (int i = 0; i < num_args; i++)
00267     {
00268       if (argv[i])
00269       {
00270         delete [] argv[i];
00271         argv[i]=NULL;
00272       }
00273     }
00274     delete [] argv;
00275     argv = NULL;
00276     num_args=0;
00277   }
00278 }
00279 
00284 int adpvm_manager::start_slave_processes(const ad_comm& _mp)
00285 {
00286   ad_comm& mp=(ad_comm&) _mp;
00287   int i,j,check;
00288   mp.get_slave_assignments();
00289   if (allocated(id)) id.deallocate();
00290   id.allocate(1,nhost,1,num_per_host);
00291   adstring slavedir;
00292   int on=0;
00293   int noptslave=0;
00294   if ( (on=option_match(ad_comm::argc,ad_comm::argv,"-dbg"))>-1)
00295      strcpy(*slave_argv,"-dbg");
00296   if ( (on=option_match(ad_comm::argc,ad_comm::argv,"-slavedir",noptslave))>-1)
00297   {
00298     if (noptslave !=1)
00299     {
00300       cerr << "Wrong number of options to -slavedir -- must be 1"
00301         " you have " << noptslave << endl;
00302       ad_exit(1);
00303     }
00304   }
00305   else
00306   {
00307     noptslave=0;
00308   }
00309   int on1,nopt1;
00310   if ( (on1=option_match(ad_comm::argc,ad_comm::argv,"-mcmc",nopt1))>-1)
00311   {
00312     if (nopt1 !=1)
00313     {
00314       cerr << "Wrong number of options to -mcmc -- must be 1"
00315         " you have " << noptslave << endl;
00316       ad_exit(1);
00317     }
00318     strcpy((*slave_argv),"-mcmc");
00319     strcpy((*slave_argv),ad_comm::argv[on1+1]);
00320   }
00321 
00322   if ( (on1=option_match(ad_comm::argc,ad_comm::argv,"-nohess"))>-1)
00323   {
00324     strcpy((*slave_argv),"-nohess");
00325   }
00326 
00327   if ( (on1=option_match(ad_comm::argc,ad_comm::argv,"-lprof"))>-1)
00328   {
00329     strcpy((*slave_argv),"-lprof");
00330   }
00331   int gdbflag=option_match(ad_comm::argc,ad_comm::argv,"-gdb");
00332 
00333   for (i=0; i<nhost; i++)      /* spawn processes on */
00334   {                            /* all physical machines */
00335     for (j=slave_assignments(i+1).indexmin();j<=slave_assignments(i+1).indexmax();
00336       j++)
00337     {
00338       strcpy((*slave_argv),"-slavename");
00339       strcpy((*slave_argv),ad_comm::adprogram_name);
00340       strcpy((*slave_argv),"-slave");
00341       strcpy((*slave_argv),(char*)(str(slave_assignments(i+1,j))));
00342       if (noptslave ==1)
00343       {
00344         strcpy((*slave_argv),"-slavedir");
00345         strcpy((*slave_argv),ad_comm::argv[on+1]);
00346       }
00347 
00348       if ( (on1=option_match(ad_comm::argc,ad_comm::argv,
00349         "-slaveargs",nopt1))>-1)
00350       {
00351         for (int i=on1;i<ad_comm::argc;i++)
00352         {
00353           strcpy(*slave_argv,ad_comm::argv[i]);
00354         }
00355       }
00356       if (gdbflag<0)
00357       {
00358         check=pvm_spawn(slave_names[1],*slave_argv ,
00359           PvmTaskHost /* | PvmTaskDebug */ ,
00360           hostp[i].hi_name, 1, &(id(i+1,j)));
00361       }
00362       else
00363       {
00364         check=pvm_spawn(slave_names[1],*slave_argv ,
00365           PvmTaskHost | PvmTaskDebug ,
00366           hostp[i].hi_name, 1, &(id(i+1,j)));
00367       }
00368       if ( (on1=option_match(ad_comm::argc,ad_comm::argv,
00369         "-slaveargs",nopt1))>-1)
00370       {
00371         for (int i=on1;i<ad_comm::argc;i++)
00372         {
00373           (*slave_argv)--;
00374         }
00375       }
00376 
00377       (*slave_argv)--;
00378       (*slave_argv)--;
00379       (*slave_argv)--;
00380       (*slave_argv)--;
00381       if (noptslave ==1)
00382       {
00383         (*slave_argv)--;
00384         (*slave_argv)--;
00385       }
00386       if (!check)
00387         printf("Couldn't start process on %s\n",hostp[i].hi_name);
00388       else
00389         printf("Started process on %s\n",hostp[i].hi_name);
00390     }
00391   }
00392   return check;
00393 }
00394 
00399 adpvm_manager::~adpvm_manager(void)
00400 {
00401   int i;
00402   // clean up slaves -- this stops all the slave processes
00403   for (i=1; i<=nhost; i++)     /* spawn processes on */
00404   {                            /* all physical machines */
00405     for (int j=slave_assignments(i).indexmin();
00406              j<=slave_assignments(i).indexmax();j++)
00407     {
00408       pvm_kill(id(i,j));
00409     }
00410   }
00411   //delete [] slave_argv;
00412   //slave_argv=NULL;
00413 }
00414 
00419 void send_cf_to_slaves(int nvar,int current_phase,const dvar_vector&  x)
00420 {
00421   // *********  begin constant send block  *************
00422   //for (int i=1;i<=ad_comm::pvm_manager->nhost;i++)
00423   //{
00424   for (int i=1; i<=ad_comm::pvm_manager-> nhost; i++)
00425   {
00426     for (int j=ad_comm::pvm_manager->slave_assignments(i+1).indexmin();
00427              j<=ad_comm::pvm_manager->slave_assignments(i+1).indexmax();j++)
00428     {
00429       int bufid = adpvm_master_cinitsend( PvmDataRaw );
00430       pvm_pack(current_phase);
00431       pvm_pack(nvar);
00432       adpvm_master_csend(ad_comm::pvm_manager->id(i,j));
00433     }
00434   }
00435   // *********  end variable send block  *************
00436 }
00437 
00442 void send_x_to_slaves(const dvar_vector&  x)
00443 {
00444   // *********  begin variable send block  *************
00445   for (int i=1; i<=ad_comm::pvm_manager-> nhost; i++)
00446   {
00447     for (int j=ad_comm::pvm_manager->slave_assignments(i).indexmin();
00448              j<=ad_comm::pvm_manager->slave_assignments(i).indexmax();j++)
00449     {
00450       int bufid = adpvm_master_vinitsend( PvmDataRaw );
00451       adpvm_pack(x);
00452       adpvm_master_vsend(ad_comm::pvm_manager->id(i,j));
00453     }
00454   }
00455   // *********  end constant send block  *************
00456 }
00457 
00462 imatrix get_int_from_slaves(void)
00463 {
00464   imatrix fslave(1,ad_comm::pvm_manager->nhost,1,ad_comm::pvm_manager->num_per_host);
00465   for (int i=1; i<=ad_comm::pvm_manager-> nhost; i++)
00466   {
00467     for (int j=ad_comm::pvm_manager->slave_assignments(i).indexmin();
00468              j<=ad_comm::pvm_manager->slave_assignments(i).indexmax();j++)
00469     {
00470       // *********  begin constant receive block  *************
00471       adpvm_master_crecv(ad_comm::pvm_manager->id(i,j)); //get the values from slave
00472       adpvm_unpack(fslave(i,j));
00473       adpvm_master_end_creceive();  // have got all the values
00474     }
00475   }
00476   // *********  end variable receive block  *************
00477   return fslave;
00478 }
00479 
00484 dvar_matrix get_f_from_slaves(void)
00485 {
00486   dvar_matrix fslave(1,ad_comm::pvm_manager->nhost,1,ad_comm::pvm_manager->num_per_host);
00487   // *********  begin variable send block  *************
00488   for (int i=1; i<=ad_comm::pvm_manager-> nhost; i++)
00489   {
00490     for (int j=ad_comm::pvm_manager->slave_assignments(i).indexmin();
00491              j<=ad_comm::pvm_manager->slave_assignments(i).indexmax();j++)
00492     {
00493       // *********  begin variable receive block  *************
00494       adpvm_master_vrecv(ad_comm::pvm_manager->id(i,j)); //get the values from slave
00495       adpvm_unpack(fslave(i,j));
00496       adpvm_master_end_vreceive();  // have got all the values
00497     }
00498   }
00499   // *********  end variable receive block  *************
00500   return fslave;
00501 }
00502 
00507 int get_int_from_master(void)
00508 {
00509   int x;
00510   int ptid=pvm_parent();
00511   // ***************  begin constant receive block *********************
00512   adpvm_slave_crecv(ptid);
00513   adpvm_unpack(x);
00514   adpvm_slave_end_creceive();
00515   // ***************  end receive block ***********************************
00516   return x;
00517 }
00518 
00523 void send_int_to_master(int i)
00524 {
00525   // ***************  begin send block ***********************************
00526   int ptid=pvm_parent();
00527   adpvm_slave_cinitsend(PvmDataDefault);/* allocate message buffer */
00528   adpvm_pack(i);
00529   adpvm_slave_csend(ptid);/* send buffer to master */
00530   // ***************  end send block ***********************************
00531 }
00532 
00537 void adpvm_manager::send_variable_values_to_slaves(void)
00538 {
00539   int i,j;
00540   //for (i=ad_comm::pvm_manager->nhost;i>=1;i--)
00541   //{
00542   for (i=1; i<=ad_comm::pvm_manager-> nhost; i++)
00543   {
00544     for (int j=ad_comm::pvm_manager->slave_assignments(i).indexmin();
00545              j<=ad_comm::pvm_manager->slave_assignments(i).indexmax();j++)
00546     {
00547       // *********  begin constant send block  *************
00548       int bufid = adpvm_master_cinitsend( PvmDataRaw );
00549       // pack all the variables
00550       for (int jj=1;jj<=initial_params::num_initial_params;jj++)
00551       {
00552         initial_params::varsptr[jj-1]->pvm_pack();
00553       }
00554       adpvm_master_csend(id(i,j));
00555       // *********  end constant send block  *************
00556     }
00557   }
00558 }
00559 
00564 void adpvm_manager::get_variable_values_from_master(void)
00565 {
00566   int i,j;
00567   // ***************  begin constant receive block *************************
00568   int ptid=pvm_parent();
00569   adpvm_slave_crecv(ptid);
00570   // unpack all the variables
00571   for (j=1;j<=initial_params::num_initial_params;j++)
00572   {
00573     initial_params::varsptr[j-1]->pvm_unpack();
00574   }
00575   adpvm_slave_end_creceive();
00576   // ***************  end receive block ***********************************
00577 }
00578 
00583 void admaster_slave_variable_interface(const ad_comm& mp)
00584 {
00585   if (ad_comm::pvm_manager)
00586   {
00587     if (ad_comm::pvm_manager->mode==1)
00588     {
00589       ad_comm::pvm_manager->start_slave_processes(mp);
00590       ad_comm::pvm_manager->send_variable_values_to_slaves();
00591     }
00592     if (ad_comm::pvm_manager->mode==2)
00593       ad_comm::pvm_manager->get_variable_values_from_master();
00594   }
00595 }
00596 #endif //#if defined(USE_ADPVM)