Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Master.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/Master.cc
11 /// @brief The Master role in elscripts, handles trajectories, generating workunits, processing of results
12 /// @author Ken Jung
13 
14 #ifdef USELUA
16 
17 #include <boost/bind.hpp>
18 #include <boost/function.hpp>
19 #include <boost/lexical_cast.hpp>
20 
21 #ifdef USEBOOSTSERIALIZE
22 #include <boost/archive/binary_oarchive.hpp>
23 #endif
24 
26 
27 #include <basic/options/option.hh>
28 #include <basic/options/keys/els.OptionKeys.gen.hh>
29 
30 #include <utility/lua/LuaIterator.hh>
31 
32 #include <utility/Factory.hh>
36 
37 #include <basic/Tracer.hh>
38 
39 // elscripts master
40 namespace protocols {
41 namespace elscripts {
42 
43 static basic::Tracer TR("protocols.elscripts.Master");
44 
45 void lregister_Master( lua_State * lstate ) {
46  lregister_BaseRole( lstate );
47  luabind::module(lstate, "protocols")
48  [
49  luabind::namespace_("elscripts")
50  [
51  luabind::class_<Master, BaseRole>("Master")
52  .def("make_wu_until_limit", &Master::make_wu_until_limit)
53  .def("make_wu", (void (Master::*) ( std::string const &, core::pose::PoseSP, protocols::moves::SerializableStateSP ) ) &Master::make_wu)
54  .def("make_wu", (void (Master::*) ( std::string const &, core::io::serialization::PipeSP, protocols::moves::SerializableStateSP ) ) &Master::make_wu)
55  .def("make_wu", (void (Master::*) ( std::string const &, core::io::serialization::PipeMapSP, protocols::moves::SerializableStateSP ) ) &Master::make_wu)
56  .def("make_wu", (void (*) ( Master *, std::string const &, core::pose::PoseSP ) ) &master_make_wu_nostate)
57  .def("make_wu", (void (*) ( Master *, std::string const &, core::io::serialization::PipeSP ) ) &master_make_wu_nostate)
58  .def("make_wu", (void (*) ( Master *, std::string const &, core::io::serialization::PipeMapSP ) ) &master_make_wu_nostate)
59  .def("interpreter", &Master::interpreter)
60  .def("end_traj", &Master::end_traj)
61  ]
62  ];
63 }
64 
65 Master::Master( int num_trajectories, boost::uint64_t mem_limit, boost::uint64_t reserved_mem, boost::uint64_t reserved_mem_multiplier) :
66  num_trajectories_(num_trajectories),
67  trajectories_mem_(0),
68  num_trajectories_finished_(0),
69  mpicounter_(10000000),
70  traj_idx_(0),
71  last_generate_initial_wu_time_( boost::posix_time::microsec_clock::universal_time() - boost::posix_time::minutes(100)),
72  BaseRole( mem_limit, reserved_mem, reserved_mem_multiplier) {
73  using namespace basic::options;
74  using namespace basic::options::OptionKeys;
75 
76  // endpoint uses this function to get role-wide memory usage
77  boost::function< boost::uint64_t ()> ref_available_mem = boost::bind( &protocols::elscripts::Master::available_mem, this );
78 
79  slave_comm_ = protocols::wum2::EndPointSP( new protocols::wum2::EndPoint( ref_available_mem ));
80 
81 
82  // initializing inputterstream
83  inputterstream_.reset ( new protocols::inputter::InputterStream (
84  inputter_rank(),
85  // num of masters
86  1
87  ) );
88 
89  lua_init();
90  lregister_Master(lstate_);
91  luabind::globals(lstate_)["master"] = this;
92  luabind::globals(lstate_)["num_trajectories"] = num_trajectories_;
93  instantiate_tasks();
94  instantiate_inputters();
95  instantiate_inputterstream();
96  instantiate_output();
97 
98  register_calculators();
99  instantiate_scorefxns();
100  instantiate_filters();
101  instantiate_movers();
102  instantiate_workunits();
103 
104  // initializing trajectories and wu counters
106  for( int i = 0; i < num_trajectories_; i++ ) {
107  trajectories_->push_back( core::pose::PoseSP() );
108  }
109 
110  // setting up a new env for each traj
111  std::string action = "DELIM(\n"
112  "traj_env = {}\n"
113  "for i=0,num_trajectories do\n"
114  " traj_env[i] = {}\n"
115  " setmetatable( traj_env[i], { __index = _G } )\n"
116  " local _ENV = traj_env[i]\n"
117  " traj_idx = i\n"
118  " wu_made = {}\n"
119  " wu_done = {}\n"
120  "end\n"
121  ")DELIM";
122  int err = luaL_dostring ( lstate_, action.c_str() );
123  if( err == 1) {
124  TR << "Setting up trajectory environments failed. Error is:" << std::endl;
125  TR << lua_tostring(lstate_, -1) << std::endl;
126  std::exit(9);
127  }
128 
129  luabind::globals(lstate_)["trajectories"] = trajectories_;
130 }
131 
132 void Master::interpreter() {
133  TR << "Switching to lua interpreter mode!" << std::endl;
134  std::string line = "";
135  int err = 0;
136  while( 1 ) {
137  std::cout << "> " << std::flush;
138  std::getline(std::cin, line);
139  if( line == "quit" ) break;
140  err = luaL_dostring ( lstate_, line.c_str() );
141  if( err == 1) {
142  std::cout << lua_tostring(lstate_, -1) << std::endl;
143  }
144  }
145  TR << "Leaving to lua interpreter mode!" << std::endl;
146 }
147 
148 void Master::go(){
149  using namespace utility::lua;
150 
151  // no while loop since Single Node will be switching between Master::go() and Slave::go()
152 
153  mpicounter_++;
154 
155  fill_trajectories();
156 
157  // dunno if this is needed, int check faster than boost time check?
158  if( mpicounter_ >= 10000000 ) {
159  // hardcoded, only try and generate initial workunits every 60 seconds
160  if ( ( boost::posix_time::microsec_clock::universal_time() - last_generate_initial_wu_time_) > boost::posix_time::seconds( 60 )){
161 
162  // generate initial wu
163  // user must be aware of memory limits if they use their own function
164  int m = luaL_dostring ( lstate_, "loop_every()" );
165  if( m == 1) {
166  TR << "calling lua function loop_every() failed. Error is:" << std::endl;
167  TR << lua_tostring(lstate_, -1) << std::endl;
168  std::exit(9);
169  }
170  last_generate_initial_wu_time_ = boost::posix_time::microsec_clock::universal_time();
171  }
172  mpicounter_ = 0;
173  }
174 
175  // process slave results
176  if( ! slave_comm_->inq().empty() ) {
177  protocols::wum2::WorkUnitSP wu = slave_comm_->inq().pop_front();
178  protocols::wum2::WorkUnit_ElScriptsSP castattempt = boost::dynamic_pointer_cast<protocols::wum2::WorkUnit_ElScripts> (wu);
179  if( castattempt != 0 ) {
180  traj_idx_ = castattempt->trajectory_idx();
181  std::string wuname = castattempt->name();
182 
183  // export new variables to lua for use in the lua fxn
184  luabind::globals(lstate_)["traj_env"][traj_idx_]["pipemap"] = castattempt->pipemap().lock();
185  luabind::globals(lstate_)["traj_env"][traj_idx_]["state"] = castattempt->state().lock();
186 
187  // calling proceed fxn
188  // also increment wu_done here to save overhead of calling into lua vm
189  std::string action = "(\n"
190  "do\n"
191  " local _ENV = traj_env[)" + boost::lexical_cast<std::string>(traj_idx_) + "(]\n"
192  " if wu_done.)"+wuname+"( == nil then\n"
193  " wu_done.)"+wuname+"( = 0\n"
194  " end\n"
195  " wu_done.)"+wuname+"( = wu_done.)"+wuname+"( + 1\n"
196  " els_setenv(_ENV)\n"
197  " els.workunits.)"+wuname+"DELIM(.proceed_on_master()\n"
198  "end\n"
199  ")DELIM";
200  int err = luaL_dostring ( lstate_, action.c_str() );
201  if( err == 1) {
202  TR << "Calling lua function for workunit " << wuname << " proceed_on_master fxn failed. Error is:" << std::endl;
203  TR << lua_tostring(lstate_, -1) << std::endl;
204  std::exit(9);
205  }
206  luabind::globals(lstate_)["traj_env"][traj_idx_]["pipemap"] = luabind::nil;
207  luabind::globals(lstate_)["traj_env"][traj_idx_]["state"] = luabind::nil;
208  lua_gc(lstate_, LUA_GCCOLLECT, 0);
209  }
210  }
211 
212 }
213 
214 // this uses the "global" traj_idx_
215 // traj_idx is set before this fxn is called
216 // this gets rid of traj_idx in lua script
217 void Master::make_wu( std::string const & wuname, core::pose::PoseSP p, protocols::moves::SerializableStateSP state ) {
218  using namespace core::io::serialization;
219  PipeSP pipe ( new Pipe() );
220  // have to copy the pose here
221  // originally, did not deep copy pose for speed reasons
222  // but then the problem becomes when boost serialize sends the pose to the slave
223  // 2 workunits can point to the same pose! because thats how it was on the master
224  // boost serialize too smart for its own good
225  pipe->push_back( core::pose::PoseSP( new core::pose::Pose(*p)) );
226  PipeMapSP pmap( new PipeMap() );
227  (*pmap)["input"] = pipe;
228  if (! state)
230  make_wu_copied( wuname, pmap, state );
231 }
232 
233 void Master::make_wu( std::string const & wuname, core::io::serialization::PipeSP p, protocols::moves::SerializableStateSP state ) {
234  using namespace core::io::serialization;
235  // have to deep copy, see make_wu( pose ) for reason
236  PipeMapSP pmap( new PipeMap() );
237  (*pmap)["input"] = core::io::serialization::clone(p);
238  if (! state)
240  make_wu_copied( wuname, pmap, state );
241 }
242 
243 void Master::make_wu( std::string const & wuname, core::io::serialization::PipeMapSP pmap, protocols::moves::SerializableStateSP state ) {
244  using namespace core::io::serialization;
245  // have to deep copy, see make_wu( pose ) for reason
247  if (! state)
249  make_wu_copied( wuname, pmap, state );
250 }
251 
252 void Master::make_wu_copied( std::string const & wuname, core::io::serialization::PipeMapSP pmap, protocols::moves::SerializableStateSP state) {
253  // if you're calling this, pmap should already be a unique instance (deep copied)
254  // and state isn't null ^^
255  using namespace core::io::serialization;
256 
258  1, traj_idx_, pmap, state, wuname
259  ));
260 
261  slave_comm_->outq().push_back( tmp );
262  if( !luabind::globals(lstate_)["traj_env"][traj_idx_]["wu_made"][wuname] ) {
263  luabind::globals(lstate_)["traj_env"][traj_idx_]["wu_made"][wuname] = 0;
264  }
265  luabind::globals(lstate_)["traj_env"][traj_idx_]["wu_made"][wuname] = luabind::object_cast<int>(luabind::globals(lstate_)["traj_env"][traj_idx_]["wu_made"][wuname]) + 1;
266 }
267 
268 void Master::make_wu_until_limit( std::string const & wuname, int num ) {
269  using namespace core::io::serialization;
270  for( int i = 0; i < num_trajectories_; i++ ){
271  if( ! (*trajectories_)[i] ) continue;
272  if( !luabind::globals(lstate_)["traj_env"][i]["wu_made"][wuname] ) {
273  luabind::globals(lstate_)["traj_env"][i]["wu_made"][wuname] = 0;
274  }
275  if( luabind::object_cast<int>(luabind::globals(lstate_)["traj_env"][i]["wu_made"][wuname]) < num ) {
276  if( mem_limit_ - current_mem() > 2 * reserved_mem_ ) {
277  PipeMapSP pmap( new PipeMap() );
278  PipeSP pipe ( new Pipe() );
279  pipe->push_back( (*trajectories_)[i] );
280  (*pmap)["input"] = pipe;
282 
284  1, i, pmap, state, wuname
285  ));
286  slave_comm_->outq().push_back( tmp );
287  luabind::globals(lstate_)["traj_env"][i]["wu_made"][wuname] = luabind::object_cast<int>(luabind::globals(lstate_)["traj_env"][i]["wu_made"][wuname]) + 1;
288  } else {
289  return;
290  }
291  }
292  }
293 }
294 
295 void Master::end_traj() {
296  (*trajectories_)[traj_idx_].reset();
297  num_trajectories_finished_++;
298  TR << "Finished " << num_trajectories_finished_ << " trajectories." << std::endl;
299 
300  // reset the traj env
301  std::string action = "(\n"
302  "i = )" + boost::lexical_cast<std::string>(traj_idx_) + "DELIM(\n"
303  "traj_env[i] = {}\n"
304  "setmetatable( traj_env[i], { __index = _G } )\n"
305  "do\n"
306  " local _ENV = traj_env[i]\n"
307  " traj_idx = i\n"
308  " wu_made = {}\n"
309  " wu_done = {}\n"
310  "end\n"
311  ")DELIM";
312  int err = luaL_dostring ( lstate_, action.c_str() );
313  if( err == 1) {
314  TR << "Cleaning up trajectory " << traj_idx_ << " environment failed. Error is:" << std::endl;
315  TR << lua_tostring(lstate_, -1) << std::endl;
316  std::exit(9);
317  }
318 }
319 
320 void Master::fill_trajectories() {
321  std::vector< int > needs_replace;
322  for( int i = 0; i < num_trajectories_; i++ ){
323  if( ! (*trajectories_)[i] )
324  needs_replace.push_back( i );
325  }
326 
327  while( needs_replace.size() != 0 && inputterstream_->has_pose() ) {
328  (*trajectories_)[ needs_replace.back() ] = inputterstream_->get_pose();
329  needs_replace.pop_back();
330  }
331  //request_pool_structures( needs_replace );
332  if( needs_replace.size() == num_trajectories_ ) {
333  TR << "Elscripts finished successfully" << std::endl;
334  exit(9);
335  }
336 }
337 
338 void Master::update_trajectories_mem(){
339 #ifdef USEBOOSTSERIALIZE
340  std::stringstream s;
341  boost::archive::binary_oarchive oa(s);
342  oa << trajectories_;
343  trajectories_mem_ = s.str().length();
344 #else
345  TR << "Memory usage tracked only if compiled against boost::serialize" << std::endl;
346 #endif
347 }
348 
349 void master_make_wu_nostate( Master * master, std::string const & wuname, core::pose::PoseSP p ) { master->make_wu( wuname, p ); }
350 void master_make_wu_nostate( Master * master, std::string const & wuname, core::io::serialization::PipeSP p ) { master->make_wu( wuname, p ); }
351 void master_make_wu_nostate( Master * master, std::string const & wuname, core::io::serialization::PipeMapSP p ){ master->make_wu( wuname, p ); }
352 
353 } //elscripts
354 } //protocols
355 #endif