Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MPI_Slave.cc
Go to the documentation of this file.
1 // -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
2 // vi: set ts=2 noet:
3 //
4 // (c) Copyright Rosetta Commons Member Institutions.
5 // (c) This file is part of the Rosetta software suite and is made available under license.
6 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
7 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
8 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
9 
10 /// @file protocols/elscripts/MPI_Slave.cc
11 /// @brief the slave role of elscripts
12 /// @author Ken Jung
13 
14 #if defined (USEBOOSTMPI) && defined (USELUA)
15 // this is useless without mpi
17 
18 #include <boost/bind.hpp>
19 #include <boost/function.hpp>
20 
22 
23 #include <basic/Tracer.hh>
24 
25 namespace protocols {
26 namespace elscripts {
27 
28 void lregister_MPI_Slave( lua_State * lstate ) {
29  lregister_Slave( lstate );
30  luabind::module(lstate, "protocols")
31  [
32  luabind::namespace_("elscripts")
33  [
34  luabind::class_<MPI_Slave, Slave>("MPI_Slave")
35  ]
36  ];
37 }
38 
39 static basic::Tracer TR("protocols.elscripts.MPI_Slave");
40 
41 MPI_Slave::MPI_Slave( boost::mpi::communicator world, int master, boost::uint64_t mem_limit, boost::uint64_t reserved_mem, boost::uint64_t reserved_mem_multiplier) :
42  world_(world),
43  Slave( master, mem_limit, reserved_mem, reserved_mem_multiplier) {
44 
45  // endpoint uses this function to get role-wide memory usage
46  boost::function< boost::uint64_t ()> ref_available_mem = boost::bind( &protocols::elscripts::MPI_Slave::available_mem, this );
47 
48  master_comm_ = protocols::wum2::EndPointSP( new protocols::wum2::MPI_EndPoint( world, ref_available_mem ) );
49 
50  lregister_MPI_Slave(lstate_);
51  luabind::globals(lstate_)["slave"] = this;
52  luabind::globals(lstate_)["rank"] = world_.rank();
53 }
54 
55 void MPI_Slave::go(){
56  using namespace utility::lua;
57 
58  // create functors to call back functions for automated endpoint processing
59  boost::function<void ( protocols::wum2::StatusResponse, int )> ref_listen_wu_sendrecv = boost::bind( &protocols::wum2::EndPoint::listen_wu_sendrecv, master_comm_, _1, _2);
60 
61  // entering main loop
62  while( 1 ) {
63  master_comm_->check_and_act_clearcommand();
64  master_comm_->check_and_act_status_request( ref_listen_wu_sendrecv );
65 
66  // check if slave doesn't have enough free memory to run WU
67  // (because wu will generate objects that take memory)
68  while( mem_limit_ - current_mem() < 2 * reserved_mem_ ) {
69  // can't run another WU, otherwise we have to throw away WU from inbuf
70  // and we should guarantee all WU sent to slave are run
71 
72  // only way to free mem is to get rid of outbound stuff
73  master_comm_->check_and_act_status_request( ref_listen_wu_sendrecv );
74  master_comm_->cleanup_reqs();
75 
76  // hopefully we rarely get to here
77  }
78 
79  // run the first wu in the queue
80  protocols::wum2::WorkUnitSP wu = master_comm_->inq().pop_front();
81  // try dynamic casts to WorkUnit_elscriptsState
82  if( wu ) {
83  protocols::wum2::WorkUnit_ElScriptsSP castattempt = boost::dynamic_pointer_cast<protocols::wum2::WorkUnit_ElScripts> (wu);
84  if( castattempt ) {
85  std::string wuname = castattempt->name();
86  // create temporary environment that will be thrown away after run()
87  std::string action = "DELIM(\n"
88  "tmp_run_env = {}\n"
89  "setmetatable(tmp_run_env, {__index = _G })\n"
90  ")DELIM";
91  int err = luaL_dostring ( lstate_, action.c_str() );
92  if( err == 1) {
93  TR << "Creating tmp namespace for run_on_slave() on slave failed. Error is:" << std::endl;
94  TR << lua_tostring(lstate_, -1) << std::endl;
95  std::exit(9);
96  }
97 
98  // exporting useful stuff to the tmp env
99  luabind::globals(lstate_)["tmp_run_env"]["pipemap"] = castattempt->pipemap().lock();
100  luabind::globals(lstate_)["tmp_run_env"]["state"] = castattempt->state().lock();
101  luabind::globals(lstate_)["tmp_run_env"]["traj_idx"] = castattempt->trajectory_idx();
102 
103  //calling run fxn
104  action = "(\n"
105  "els_setenv(tmp_run_env)\n"
106  "els.workunits.)"+wuname+"DELIM(.run_on_slave()\n"
107  "tmp_run_env = {} -- delete tmp_env after calling run_on_slave()\n"
108  ")DELIM";
109  err = luaL_dostring ( lstate_, action.c_str() );
110  if( err == 1) {
111  TR << "Calling lua function for workunit " << wuname << " run_on_slave fxn failed. Error is:" << std::endl;
112  TR << lua_tostring(lstate_, -1) << std::endl;
113  std::exit(9);
114  }
115  lua_gc(lstate_, LUA_GCCOLLECT, 0);
116  // shallow copy! works fine for my purposes
117  protocols::wum2::WorkUnitSP result_wu( new protocols::wum2::WorkUnit_ElScripts( *castattempt ) );
118  master_comm_->outq().push_back( result_wu );
119  } else {
120  wu->run();
121  }
122  }
123 
124  // moves inbuf to inq
125  // cleans up outbuf
126  master_comm_->cleanup_reqs();
127  }
128 }
129 
130 
131 } //elscripts
132 } //protocols
133 #endif