Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MPIPool_ConvergenceCheck.cc
Go to the documentation of this file.
1 #ifdef USEMPI
4 #include <core/pose/Pose.hh>
5 #include <ObjexxFCL/FArray2D.hh>
8 #include <basic/Tracer.hh>
11 #include <protocols/jd2/util.hh>
12 #include <ObjexxFCL/format.hh>
13 #include <fstream>
14 #include <basic/prof.hh>
15 #include <utility/io/mpistream.hh>
16 #include "mpi.h"
17 
18 //SilentFileStuff
22 
23 //option stuff
24 #include <basic/options/option.hh>
25 #include <basic/options/after_opts.hh>
26 #include <basic/options/option_macros.hh>
27 
28 
29 //profiling
30 #include <basic/prof.hh>
31 //OPT_2GRP_KEY(String, sampling, out, new_structures )
32 
33 namespace protocols {
34 namespace canonical_sampling{
35 namespace mc_convergence_checks {
36 
37 static basic::Tracer tr("MPIPool_ConvergenceCheck");
38 
39  //bool protocols::canonical_sampling::mc_convergence_checks::MPIPool_RMSD::options_registered_( false );
40 
41  //
43 
44 using namespace ObjexxFCL;
45 using namespace core;
46 using namespace utility::io::mpi_stream;
47 using namespace core::io::silent;
48 
49 int const POSE_TRANSFER = 2000;
50 int const TAG_TRANSFER = 2001;
51 int const MPI_UPDATE = 1000;
52 int const MPI_ADD_POSE_TO_POOL = 1001;
53 int const MPI_DATA_TRANSFER = 1003;
54 int const MPI_BOOL = 1006;
55 int const UPDATE_MISSING_POSE = 1004;
56 int const MPI_REPORT_SIZE = 1007;
57 int const MPI_FINISHED = 1008;
58  //int const MASTER_NODE = master_node_;
59 
60 
61 
62 typedef FArray2P<double> FArray2P_double;
63 typedef FArray2D<double> FArray2D_double;
64 
65 
66 
68  Pool_RMSD( silent_file ),
69  trajectories_finished_( 0 ),
70  new_structures_( 0 ),
71  rank_( 0 ),
72  npes_( 0 ),
73  transition_threshold_(-1),
74  new_decoys_out_( "discovered_decoys.out" )
75 {
76  initialize();
77  tr.Debug << "checking: rank " << rank_ << " has " << Pool_RMSD::size() << " structures in its pool " << std::endl;
78 }
79 
80  /**
81 void
82 MPIPool_RMSD::register_options(){
83  using namespace basic::options;
84  using namespace basic::options::OptionKeys;
85 
86  if( !options_registered_ ){
87  tr.Debug << "registering options for sampling::out::new_structures " << std::endl;
88  NEW_OPT( sampling::out::new_structures, "write structures above transition_threshold to this file", "discovered_decoys.out" );
89  options_registered_ = true;
90  }
91 }
92 
93 void
94 MPIPool_RMSD::set_defaults_from_cmdline(){
95  using namespace basic::options;
96  using namespace basic::options::OptionKeys;
97 
98  runtime_assert( options_registered_ );
99  new_decoys_out_ = option[ sampling::out::new_structures ] ;
100 }
101  **/
102 
103 
105  PROF_START( basic::CHECK_COMM_SIZE );
106  MPI_Comm_rank( MPI_COMM_WORLD, ( int* )( &rank_ ) );
107  MPI_Comm_size( MPI_COMM_WORLD, ( int* )( &npes_ ) );
108  PROF_STOP( basic::CHECK_COMM_SIZE );
109 
110  // register_options();
111  // set_defaults_from_cmdline();
112 
113  if( rank_ == master_node_ ){
114  tr.Debug << "initializing master pool. setting pool_size_ " << Pool_RMSD::size() << std::endl;
117  runtime_assert( Pool_RMSD::size() == 0 );
118  }else{
120  }
121 }
122 
124  new_structures_ += num_to_add;
125 }
126 
127 void MPIPool_RMSD::send_update( int const receiving_rank, int message_type){
128  PROF_START( basic::MPI_SEND_UPDATE );
129  tr.Debug << rank_ << " is sending an update message of type " << message_type << " to " << receiving_rank << std::endl;
130  MPI_Send( &message_type, 1, MPI_INT, receiving_rank, MPI_UPDATE, MPI_COMM_WORLD );
131  PROF_STOP( basic::MPI_SEND_UPDATE );
132 }
133 
134 void MPIPool_RMSD::field_message( int& sending_rank, int& message_type ){
135 
136  PROF_START( basic::MPI_SEND_UPDATE );
137  MPI_Status stat;
138  MPI_Recv( &message_type, 1, MPI_INT, MPI_ANY_SOURCE, MPI_UPDATE, MPI_COMM_WORLD, &stat );
139  sending_rank = stat.MPI_SOURCE;
140  tr.Debug << "from " << sending_rank << " received an update message_type: " << message_type << std::endl;
141  PROF_STOP( basic::MPI_SEND_UPDATE );
142 }
143 
144 
145  // function only used by master node
146 void MPIPool_RMSD::send_newest_xyz( core::Size num_to_send, int const receiving_rank ){
147  core::Size current_size = new_structures_;
148  runtime_assert( new_structures_ >= num_to_send );
149  while( num_to_send > 0 ){
150  FArray2D<double> coords;
151  Pool_RMSD::get( current_size - num_to_send + 1, coords );
152  std::string tag = Pool_RMSD::get_tag( current_size - num_to_send + 1);
153  tr.Debug << "Sending " << tag << " from rank " << rank_ <<
154  " at index " << (current_size - num_to_send + 1) <<
155  " current size is " << current_size <<
156  " num to send is " << num_to_send <<
157  " to receiving_rank " << receiving_rank << std::endl;
158  send_xyz( coords, tag, receiving_rank );
159  num_to_send--;
160  }
161 }
162 
164  FArray2D<double>& xyz,
165  std::string& tag,
166  core::Size receiving_rank
167 ){
169  farray_to_string( xyz, coords );
170  std::ostringstream double_to_string;
171  double_to_string.str( coords );
172 
173  PROF_START( basic::MPI_SLAVE_REPORT_SIZES );
174  int buf[ 4 ];
175  buf[ 0 ] = xyz.u1();
176  buf[ 1 ] = xyz.u2();
177  buf[ 2 ] = (double_to_string.str()).size();
178  buf[ 3 ] = tag.size();
179 
180  MPI_Send( &buf, 4, MPI_INT, receiving_rank, POSE_TRANSFER, MPI_COMM_WORLD );
181  PROF_STOP( basic::MPI_SLAVE_REPORT_SIZES );
182  PROF_START( basic::MPI_SLAVE_REPORT_NEW_COORDS );
183  MPI_Send(
184  const_cast<char*> (double_to_string.str().data()),
185  (double_to_string.str()).size(),
186  MPI_CHAR,
187  receiving_rank,
188  MPI_DATA_TRANSFER,
189  MPI_COMM_WORLD
190  );
191  tr.Debug << receiving_rank << " sending tag " << tag << std::endl;
192  MPI_Send( const_cast<char*> (tag.data()), tag.size(), MPI_CHAR, receiving_rank, TAG_TRANSFER, MPI_COMM_WORLD );
193  PROF_STOP( basic::MPI_SLAVE_REPORT_NEW_COORDS );
194 }
195 
197  FArray2D<double>& xyz,
198  std::string& string
199 ){
200  PROF_START( basic::FARRAY_MANIPULATION );
201  std::ostringstream double_to_string;
202  for( unsigned i = 1; i <= xyz.u1(); i++ ){
203  for( unsigned j = 1; j <= xyz.u2(); j++ ){
204  double_to_string << xyz( i, j ) << " ";
205  }
206  }
207  string = double_to_string.str();
208  PROF_STOP( basic::FARRAY_MANIPULATION );
209 }
210 
211 void MPIPool_RMSD::receive_newest_xyz( core::Size num_to_get, int const sending_rank ){
212  while( num_to_get > 0 ){
213  FArray2D<double> coords;
215  receive_xyz( coords, tag, sending_rank );
216  num_to_get--;
217  Pool_RMSD::add( coords, coords.u2(), tag );
218  tr.Debug << "added pose (receive_newest_xyz) now has " << Pool_RMSD::size() << std::endl;
219  }
220 }
221 
223  FArray2D<double>& xyz,
224  std::string& tag,
225  core::Size sending_rank
226 ){
227 
228  PROF_START( basic::MPI_SLAVE_REPORT_SIZES );
229  int buf[ 4 ];
230  MPI_Status stat;
231  MPI_Recv( &buf, 4, MPI_INT, sending_rank, POSE_TRANSFER, MPI_COMM_WORLD, &stat );
232  core::Size xyz_u1;
233  core::Size xyz_u2;
234  core::Size received_string_size;
235  core::Size tag_size;
236  xyz_u1 = buf[ 0 ];
237  xyz_u2 = buf[ 1 ];
238  received_string_size = buf[ 2 ];
239  tag_size = buf[ 3 ];
240  PROF_STOP( basic::MPI_SLAVE_REPORT_SIZES );
241  core::Size index = 0;
242  xyz.dimension( xyz_u1, xyz_u2, 0.0 );
243  std::string data;
244  PROF_START( basic::MPI_SLAVE_REPORT_NEW_COORDS );
245  char *matrix = new char[ received_string_size + 1 ];
246 
247  MPI_Recv( matrix, received_string_size , MPI_CHAR, sending_rank, MPI_DATA_TRANSFER, MPI_COMM_WORLD, &stat );
248  data.assign( matrix, received_string_size );
249  string_to_farray( xyz, data, xyz_u1, xyz_u2 );
250  char *cbuf = new char[tag_size+1];
251  MPI_Recv( cbuf, tag_size, MPI_CHAR, sending_rank, TAG_TRANSFER, MPI_COMM_WORLD, &stat );
252  tag.assign( cbuf, tag_size );
253  PROF_STOP( basic::MPI_SLAVE_REPORT_NEW_COORDS );
254  //tr.Debug << sending_rank << " RECEIVED TAG " << tag << std::endl;
255 }
256 
257 void MPIPool_RMSD::string_to_farray( FArray2D<double>& xyz, std::string& string, int xyz_u1, int xyz_u2 ){
258  std::istringstream string_to_double;
259  string_to_double.str(string);
260  PROF_START( basic::FARRAY_MANIPULATION );
261  double element;
262  for(core::Size i = 1; i <= xyz_u1; i++ ){
263  for(core::Size j = 1; j <= xyz_u2; j++ ){
264  string_to_double >> element;
265  xyz( i, j ) = element;
266  }
267  }
268  PROF_STOP( basic::FARRAY_MANIPULATION );
269 }
270 
272  transition_threshold_ = threshold;
273 }
274 
276  new_decoys_out_ = new_out;
277 }
278 
280  return new_decoys_out_;
281 }
282 
284  int target_rank_pool_size;
285  int my_pool_size = pool_size_ + new_structures_;
286  tr.Debug << "(get_pool_diff) current size is " << my_pool_size << std::endl;
287  int num_diff;
288  MPI_Status status;
289  if(rank_ == master_node_){
290  PROF_START( basic::MPI_SYNC_POOL_DIFF );
291  MPI_Recv( &target_rank_pool_size, 1, MPI_INT, target_rank, MPI_REPORT_SIZE, MPI_COMM_WORLD, &status );
292  num_diff = my_pool_size - target_rank_pool_size;
293  MPI_Send( &num_diff, 1, MPI_INT, target_rank, MPI_REPORT_SIZE, MPI_COMM_WORLD );
294  tr.Debug << "MASTER NODE HAS " << my_pool_size << " AND SLAVE HAS " << target_rank_pool_size << " SO NEED TO UPDATE " << num_diff << " LAST POSES " << std::endl;
295  PROF_STOP( basic::MPI_SYNC_POOL_DIFF );
296  }else{
297  PROF_START( basic::MPI_SYNC_POOL_DIFF );
298  MPI_Send( &my_pool_size, 1, MPI_INT, master_node_, MPI_REPORT_SIZE, MPI_COMM_WORLD );
299  MPI_Recv( &num_diff, 1, MPI_INT, master_node_, MPI_REPORT_SIZE, MPI_COMM_WORLD, &status );
300  PROF_STOP( basic::MPI_SYNC_POOL_DIFF );
301  }
302 
303  return num_diff;
304 }
305 
306 void MPIPool_RMSD::send_accepted(bool truefalse, core::Size rank){
307  int bool_to_int = 0;
308  if( truefalse ){
309  bool_to_int = 1;
310  }
311  tr.Debug << "(send_accepted)sending to rank " << rank << " " << truefalse << std::endl;
312  PROF_START( basic::MPI_SEND_ACCEPTED );
313  MPI_Send( &bool_to_int, 1, MPI_INT, rank, MPI_BOOL, MPI_COMM_WORLD );
314  PROF_STOP( basic::MPI_SEND_ACCEPTED );
315 }
316 
318  int bool_to_int;
319  MPI_Status stat;
320  PROF_START( basic::MPI_SEND_ACCEPTED );
321  MPI_Recv( &bool_to_int, 1, MPI_INT, rank, MPI_BOOL, MPI_COMM_WORLD, &stat );
322  PROF_STOP( basic::MPI_SEND_ACCEPTED );
323  if( bool_to_int == 1){
324  return true;
325  }else{
326  return false;
327  }
328 }
329 
330 
332  if(trajectories_finished_ < ( npes_ - master_node_ - 1 ) ){
333  tr.Debug << "num trajectories finished: " <<
334  trajectories_finished_ << " needed: " <<
335  ( npes_ - master_node_ - 1 ) << std::endl;
336  return false;
337  }else{
338  tr.Debug << "FINISHED! num trajectories finished: " <<
339  trajectories_finished_ << " needed: " <<
340  ( npes_ - master_node_ - 1 ) << std::endl;
341  return true;
342  }
343 }
344 
346  if( rank_ != master_node_ ){
347  tr.Debug << "sending finalized message to master" << std::endl;
348  send_update( master_node_, MPI_FINISHED );
349  }
350 }
351 
352 
354  tr.Debug << "in master go master rank is " << rank_ << std::endl;
355 
356  PROF_START( basic::MPICANONICALSAMPLING );
357  while( !trajectories_finished() ){
358 
359  int slave_rank = -1;
360  int message_type;
361  field_message( slave_rank /**receive update from any node*/, message_type );
362 
363  if( message_type == UPDATE_MISSING_POSE ){
364  core::Size num_to_update = get_pool_diff( slave_rank );
365  send_newest_xyz( num_to_update, slave_rank );
366  }
367  else if(message_type == MPI_ADD_POSE_TO_POOL){
368  //tr.Debug << "received message to add pose to pool" << std::endl;
369  FArray2D<double> new_coords;
370  std::string new_tag;
371 
372  receive_xyz( new_coords, new_tag, slave_rank );
373  core::Size num_recent_updates = get_pool_diff( slave_rank );
374  send_newest_xyz( num_recent_updates, slave_rank );
375  core::Real best_rmsd = -1; std::string best_decoy;
376  bool is_accepted = false;
377  if( num_recent_updates == 0 ){ //no additions during evaluation
378  Pool_RMSD::add( new_coords, new_coords.u2(), new_tag );
380  // DEBUG OUTPUT
381  /**
382  std::ofstream debug_cl_cnters;
383  std::ostringstream q;
384  q << rank_;
385  debug_cl_cnters.open((q.str() + ".debug_cl_centers.txt").c_str(),std::fstream::app);
386  debug_cl_cnters << new_tag << std::endl;
387  **/
388  //DEBUG OUTPUT
389 
390  tr.Debug << "MASTER: coords just added. pool size is now " << (pool_size_ + new_structures_)
391  << " pool_size_ is " << pool_size_
392  << " new_structures_ " << new_structures_
393  << " real size is: " << Pool_RMSD::size() << std::endl;
394  is_accepted = true;
395  }else{
396  runtime_assert( new_structures_ >= num_recent_updates );
397  tr.Debug << "starting evaluation from index: " << (new_structures_ - num_recent_updates +1) << " of " << new_structures_ << std::endl;
398  Pool_RMSD::evaluate( new_coords, best_decoy, best_rmsd, (new_structures_ - num_recent_updates +1) );
399  runtime_assert( transition_threshold_ != -1 );
400  if( best_rmsd > transition_threshold_ ){
401  tr.Debug << "best_rmsd " << best_rmsd <<
402  " greater than transition threshold " << transition_threshold_ << std::endl;
403  is_accepted = true;
404  Pool_RMSD::add( new_coords, new_coords.u2(), new_tag );
406  tr.Debug << " coords just added. pool size is now " << (pool_size_ + new_structures_) << " real size is " << Pool_RMSD::size() << std::endl;
407  // DEBUG OUTPUT
408  /**
409  std::ofstream debug_cl_cnters;
410  std::ostringstream q;
411  q << rank_;
412  debug_cl_cnters.open((q.str() + ".debug_cl_centers.txt").c_str(),std::fstream::app);
413  debug_cl_cnters << new_tag << std::endl;
414  **/
415  //DEBUG OUTPUT
416  }
417  }
418  send_accepted( is_accepted, slave_rank );
419  }else if( message_type == MPI_FINISHED ){
421  }
422  }
423  PROF_STOP( basic::MPICANONICALSAMPLING );
424  tr.Debug << "master node finished " << std::endl;
425  return;
426 }
427 
429  tr.Debug << "testing if is master node: rank is " << rank_ << " and master node rank is " << master_node_ << std::endl;
430  return rank_ == master_node_;
431 }
432 
434  core::pose::Pose const& pose,
435  std::string& best_decoy,
436  core::Real& best_rmsd,
437  core::Real transition_threshold
438  ){
439 
440  runtime_assert(transition_threshold == transition_threshold_);
441 
442  tr.Debug << "node is rank " << rank_ << " out of " << npes_ << std::endl;
443  tr.Debug << " using MPIPool_RMSD::evaluate_and_add" << std::endl;
444  core::Size best_index = -1;
445 
446  PROF_START( basic::MPICANONICALSAMPLING );
447 
448  send_update( master_node_, UPDATE_MISSING_POSE );
449  core::Size num_to_update = get_pool_diff( rank_ );
450  receive_newest_xyz( num_to_update, master_node_ );
451  increment_pool_size( num_to_update );
452  tr.Debug << " slave pool just received " << num_to_update << " pool_size is now " << (pool_size_ + new_structures_ ) << " real size: " << Pool_RMSD::size() << std::endl;
453  //runtime_assert(get_pool_diff( rank_ ) == 0);
454 
455  PROF_STOP( basic::MPICANONICALSAMPLING );
456 
457  best_index = Pool_RMSD::evaluate( pose, best_decoy, best_rmsd );
458  tr.Debug << "best rmsd after evaluation is " << best_rmsd << " threadhol " << transition_threshold << std::endl;
459  if(best_rmsd > transition_threshold){
460  tr.Debug << "best_rmsd is " << best_rmsd << " which is greater than transition_threshold, adding pose to pool " << std::endl;
461 
462  PROF_START( basic::MPICANONICALSAMPLING );
463 
464  send_update( master_node_, MPI_ADD_POSE_TO_POOL );
465  FArray2D_double coords( 3, pose.total_residue() , 0.0 );
466  PROF_START( basic::FARRAY_MANIPULATION );
468  PROF_STOP( basic::FARRAY_MANIPULATION );
469  //assign new tag based on olli's scheme
471  std::string new_cluster_tag = "new."+lead_zero_string_of( Pool_RMSD::size(), 8 )+".0"+"_"+jobname;
472 
473  send_xyz( coords, new_cluster_tag, master_node_ );
474  core::Size num_recent_updates = get_pool_diff( rank_ );
475  receive_newest_xyz( num_recent_updates, master_node_ );
476  increment_pool_size( num_recent_updates );
477  tr.Debug << " slave pool just received " << num_recent_updates << " pool_size is now " << ( pool_size_ + new_structures_ ) << " real size: " << Pool_RMSD::size() << std::endl;
478  //runtime_assert(get_pool_diff( rank_ ) == 0);
479  bool is_accepted = receive_is_accepted( master_node_ );
480 
481  PROF_STOP( basic::MPICANONICALSAMPLING );
482 
483  if( is_accepted ){
484  tr.Debug << "master accepted new pose(evaluate). adding new pose to pool, "
485  << Pool_RMSD::size() << std::endl;
486 
487  Pool_RMSD::add( coords, coords.u2(), new_cluster_tag );
488 
489  PROF_START( basic::WRITE_TO_FILE );
491  ss->fill_struct( pose, new_cluster_tag );
493  sfd.write_silent_struct( *ss, new_decoys_out_, false );
494  PROF_STOP( basic::WRITE_TO_FILE );
495 
497  tr.Debug << " coords just added size is now " << ( pool_size_ + new_structures_ ) << " and real size is " << Pool_RMSD::size() << std::endl;
498  }
499  }
500  return best_index;
501 }
502 
503 
504 } //mc_convergence_checks
505 } //moves
506 } //protocols
507 #else
508 #endif