Rosetta
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
mpi_util.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 utility/mpi_util.hh
11 /// @brief
12 /// @author Andrew Leaver-Fay (aleaverfay@gmail.com)
13 
14 // Unit headers
15 #include <utility/mpi_util.hh>
16 #include <utility/SimulateMPI.hh>
17 
18 namespace utility {
19 
20 
21 #ifdef USEMPI
22 
23 #define MPI_ONLY(x) x
24 
25 int
26 mpi_rank() {
27  int return_val( 0 );
28  MPI_Comm_rank( MPI_COMM_WORLD, & return_val);/* get current process id */
29  return return_val;
30 }
31 
32 
33 int
34 mpi_nprocs()
35 {
36  int return_val( 0 );
37  MPI_Comm_size( MPI_COMM_WORLD, & return_val);/* get number of processes */
38  return return_val;
39 }
40 
41 /// @details This call will block until some node sends an integer. Useful in
42 /// server/client arrangements where node 0 waits for a node to say "I'm ready
43 /// to communicate with you" before then sending several other messages. In
44 /// order for this to work, node 0 first needs to wait for a communication from
45 /// anyone and then needs to know which node it is that it will receive specific
46 /// communications from (so that it doesn't confuse messages that may be coming
47 /// from other nodes with the messages its waiting for from the particular node).
48 /// That is, node 0 must only be willing to wait for communication from anyone
49 /// in one spot, and after that, must accept messages only from a single process.
50 /// For this to work, the message that node 0 must accept is the mpi-rank of the
51 /// process it's about to have further communications with. The client node is
52 /// effectively saying "Me me me. Talk to me."
53 int
55 {
56  //std::cerr << "receive_integer_from_anyone " << mpi_rank() << std::endl;
57 
58  int communicating_node;
59  MPI_Status status;
60  MPI_Recv( &communicating_node, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status );
61  return communicating_node;
62 }
63 
64 
65 std::string
67  int source
68 ) {
69  //std::cerr << "receive_string_from_node " << mpi_rank() << std::endl;
70 
71  std::string return_val;
72  int len( 0 );
73  int tag( 1 );
74  MPI_Status stat;
75  MPI_Recv( &len, 1, MPI_INT, source, tag, MPI_COMM_WORLD, & stat );
76  char * str = new char[ len + 1 ];
77  str[ len ] = '\0'; // ? do I need null terminated strings?
78  MPI_Recv( str, len, MPI_CHAR, source, tag, MPI_COMM_WORLD, & stat );
79  return_val = std::string( str, len );
80  delete [] str;
81  return return_val;
82 }
83 
84 void
86  int destination,
87  std::string const & message
88 ) {
89  //std::cerr << "send_string_to_node " << mpi_rank() << std::endl;
90 
91  int tag( 1 );
92  int len( message.size() );
93  MPI_Send( &len, 1, MPI_INT, destination, tag, MPI_COMM_WORLD );
94  MPI_Send( const_cast< char * > (message.c_str()), len, MPI_CHAR, destination, tag, MPI_COMM_WORLD );
95 }
96 
97 
98 char
100  int source
101 ) {
102  //std::cerr << "receive_char_from_node " << mpi_rank() << std::endl;
103 
104  char return_val = 0;
105  int tag( 1 );
106  MPI_Status stat;
107  MPI_Recv( &return_val, 1, MPI_CHAR, source, tag, MPI_COMM_WORLD, & stat );
108  return return_val;
109 }
110 
111 void
113  int destination,
114  char message
115 ) {
116  //std::cerr << "send_char_to_node " << mpi_rank() << std::endl;
117  int tag( 1 );
118  MPI_Send( &message, 1, MPI_CHAR, destination, tag, MPI_COMM_WORLD );
119 }
120 
121 int
123  int source
124 ) {
125  //std::cerr << "receive_integer_from_node " << mpi_rank() << std::endl;
126 
127  int return_val(0);
128  int tag( 1 );
129  MPI_Status stat;
130  MPI_Recv( &return_val, 1, MPI_INT, source, tag, MPI_COMM_WORLD, & stat );
131  return return_val;
132 }
133 
134 
135 void
137  int destination,
138  int message
139 ) {
140  //std::cerr << "send_integer_to_node " << mpi_rank() << std::endl;
141 
142  int tag( 1 );
143  MPI_Send( &message, 1, MPI_INT, destination, tag, MPI_COMM_WORLD );
144 }
145 
146 
149  int source
150 ) {
151  //std::cerr << "receive_integers_from_node " << mpi_rank() << std::endl;
152 
153  utility::vector1< int > return_val;
154  int len( 0 );
155  int tag( 1 );
156  MPI_Status stat;
157  MPI_Recv( &len, 1, MPI_INT, source, tag, MPI_COMM_WORLD, & stat );
158  if ( len != 0 ) {
159  return_val.resize( len );
160  int * intarray = new int[ len ];
161  MPI_Recv( intarray, len, MPI_INT, source, tag, MPI_COMM_WORLD, & stat );
162  for ( int ii = 0; ii < len; ++ii ) return_val[ ii + 1 ] = intarray[ ii ];
163  delete [] intarray;
164  }
165  return return_val;
166 }
167 
168 
169 void
171  int destination,
172  utility::vector1< int > const & message
173 ) {
174  //std::cerr << "send_integers_to_node " << mpi_rank() << std::endl;
175 
176  int tag( 1 );
177  int len( message.size() );
178  MPI_Send( &len, 1, MPI_INT, destination, tag, MPI_COMM_WORLD );
179  if ( len != 0 ) {
180  MPI_Send( const_cast< int * > (&message[1]), len, MPI_INT, destination, tag, MPI_COMM_WORLD );
181  }
182 }
183 
184 double
186  int source
187 ) {
188  //std::cerr << "receive_double_from_node " << mpi_rank() << std::endl;
189 
190  double return_val(0);
191  int tag( 1 );
192  MPI_Status stat;
193  MPI_Recv( &return_val, 1, MPI_DOUBLE, source, tag, MPI_COMM_WORLD, & stat );
194  return return_val;
195 }
196 
197 
198 void
200  int destination,
201  double message
202 ) {
203  //std::cerr << "send_double_to_node " << mpi_rank() << std::endl;
204 
205  int tag( 1 );
206  MPI_Send( &message, 1, MPI_DOUBLE, destination, tag, MPI_COMM_WORLD );
207 }
208 
209 
212  int source
213 ) {
214  //std::cerr << "receive_doubles_from_node " << mpi_rank() << std::endl;
215 
216  utility::vector1< double > return_val;
217  int len( 0 );
218  int tag( 1 );
219  MPI_Status stat;
220  MPI_Recv( &len, 1, MPI_INT, source, tag, MPI_COMM_WORLD, & stat );
221  if ( len != 0 ) {
222  return_val.resize( len );
223  double * doublearray = new double[ len ];
224  MPI_Recv( doublearray, len, MPI_DOUBLE, source, tag, MPI_COMM_WORLD, & stat );
225  for ( int ii = 0; ii < len; ++ii ) return_val[ ii + 1 ] = doublearray[ ii ];
226  delete [] doublearray;
227  }
228  return return_val;
229 }
230 
231 
232 void
234  int destination,
235  utility::vector1< double > const & message
236 ) {
237  //std::cerr << "send_doubles_to_node " << mpi_rank() << std::endl;
238 
239  int tag( 1 );
240  int len( message.size() );
241  MPI_Send( &len, 1, MPI_INT, destination, tag, MPI_COMM_WORLD );
242  if ( len != 0 ) {
243  MPI_Send( const_cast< double * > (&message[1]), len, MPI_DOUBLE, destination, tag, MPI_COMM_WORLD );
244  }
245 }
246 
247 ////////////////////////////
248 #else // USEMPI is not used
249 ///////////////////////////
250 
251 #define MPI_ONLY(x)
252 
253 int
255  if ( SimulateMPI::simulate_mpi() ) {
256  return SimulateMPI::mpi_rank();
257  } else {
258  int return_val( 0 );
259  return return_val;
260  }
261 }
262 
263 
264 int
266 {
267  if ( SimulateMPI::simulate_mpi() ) {
268  return SimulateMPI::mpi_nprocs();
269  } else {
270  int return_val( 1 );
271  return return_val;
272  }
273 }
274 
275 int
277 {
278  if ( SimulateMPI::simulate_mpi() ) {
280  } else {
281  int return_val = 0;
282  return return_val;
283  }
284 }
285 
286 
287 std::string
289  int source
290 ) {
291  if ( SimulateMPI::simulate_mpi() ) {
293  } else {
294  std::string return_val;
295  return return_val;
296  }
297 }
298 
299 void
301  int destination,
302  std::string const & message)
303 {
304  if ( SimulateMPI::simulate_mpi() ) {
305  SimulateMPI::send_string_to_node(destination, message);
306  } else {
307  return;
308  }
309 }
310 
311 char
313  int source
314 ) {
315  if ( SimulateMPI::simulate_mpi() ) {
317  } else {
318  char return_val = 0;
319  return return_val;
320  }
321 }
322 
323 void
325  int destination,
326  char message)
327 {
328  if ( SimulateMPI::simulate_mpi() ) {
329  SimulateMPI::send_char_to_node(destination, message);
330  } else {
331  return;
332  }
333 }
334 
335 int
337  int source
338 ) {
339  if ( SimulateMPI::simulate_mpi() ) {
341  } else {
342  int return_val = 0;
343  return return_val;
344  }
345 }
346 
347 void
349  int destination,
350  int message)
351 {
352  if ( SimulateMPI::simulate_mpi() ) {
353  SimulateMPI::send_integer_to_node(destination, message);
354  } else {
355  return;
356  }
357 }
358 
361  int source
362 ) {
363  if ( SimulateMPI::simulate_mpi() ) {
365  } else {
366  utility::vector1< int > return_val;
367  return return_val;
368  }
369 }
370 
371 void
373  int destination,
374  utility::vector1< int > const & message)
375 {
376  if ( SimulateMPI::simulate_mpi() ) {
377  SimulateMPI::send_integers_to_node(destination, message);
378  } else {
379  return;
380  }
381 }
382 
383 
384 double
386  int source
387 ) {
388  if ( SimulateMPI::simulate_mpi() ) {
390  } else {
391  double return_val = 0;
392  return return_val;
393  }
394 }
395 
396 void
398  int destination,
399  double message)
400 {
401  if ( SimulateMPI::simulate_mpi() ) {
402  SimulateMPI::send_double_to_node(destination, message);
403  } else {
404  return;
405  }
406 }
407 
410  int source
411 ) {
412  if ( SimulateMPI::simulate_mpi() ) {
414  } else {
415  utility::vector1< double > return_val;
416  return return_val;
417  }
418 }
419 
420 void
422  int destination,
423  utility::vector1< double > const & message)
424 {
425  if ( SimulateMPI::simulate_mpi() ) {
426  SimulateMPI::send_doubles_to_node(destination, message);
427  } else {
428  return;
429  }
430 }
431 
432 
433 #endif // USEMPI
434 
435 
436 }
437 
void send_double_to_node(int destination, double message)
Definition: mpi_util.cc:397
int receive_integer_from_node(int source)
Use MPI to receive a single integer from a particular node.
Definition: mpi_util.cc:336
def status
static double receive_double_from_node(int source)
Definition: SimulateMPI.cc:324
static void send_integer_to_node(int destination, int message)
Definition: SimulateMPI.cc:279
void send_doubles_to_node(int destination, utility::vector1< double > const &message)
Definition: mpi_util.cc:421
static bool simulate_mpi()
Definition: SimulateMPI.cc:176
static void send_double_to_node(int destination, double message)
Definition: SimulateMPI.cc:336
static vector1< double > receive_doubles_from_node(int source)
Definition: SimulateMPI.cc:352
static int receive_integer_from_anyone()
Definition: SimulateMPI.cc:202
static std::string receive_string_from_node(int source)
Definition: SimulateMPI.cc:209
void send_string_to_node(int destination, std::string const &message)
Definition: mpi_util.cc:300
static char receive_char_from_node(int source)
Definition: SimulateMPI.cc:238
Fstring::size_type len(Fstring const &s)
Length.
Definition: Fstring.hh:2207
static void send_integers_to_node(int destination, vector1< int > const &message)
Definition: SimulateMPI.cc:307
void send_integer_to_node(int destination, int message)
Definition: mpi_util.cc:348
static void send_char_to_node(int destination, char message)
Definition: SimulateMPI.cc:250
utility::vector1< int > receive_integers_from_node(int source)
Use MPI to receive a vector of integers from a particular node.
Definition: mpi_util.cc:360
char receive_char_from_node(int source)
Use MPI to receive a single char from a particular node.
Definition: mpi_util.cc:312
int receive_integer_from_anyone()
Use MPI to wait until some node sends an integer – usually its own mpi_rank so that it can send furt...
Definition: mpi_util.cc:276
static void send_string_to_node(int destination, std::string const &message)
Definition: SimulateMPI.cc:221
static int receive_integer_from_node(int source)
Definition: SimulateMPI.cc:267
void send_integers_to_node(int destination, utility::vector1< int > const &message)
Definition: mpi_util.cc:372
int mpi_rank()
Definition: mpi_util.cc:254
utility::vector1< double > receive_doubles_from_node(int source)
Use MPI to receive a vector of doubles from a particular node.
Definition: mpi_util.cc:409
std::string receive_string_from_node(int source)
Use MPI to receive a string from a particular node.
Definition: mpi_util.cc:288
static vector1< int > receive_integers_from_node(int source)
Definition: SimulateMPI.cc:295
void send_char_to_node(int destination, char message)
Definition: mpi_util.cc:324
rule< Scanner, tag_closure::context_t > tag
Definition: Tag.cc:373
int mpi_nprocs()
Definition: mpi_util.cc:265
static int mpi_nprocs()
Definition: SimulateMPI.cc:197
static int mpi_rank()
Definition: SimulateMPI.cc:191
double receive_double_from_node(int source)
Use MPI to receive a single double from a particular node.
Definition: mpi_util.cc:385
static void send_doubles_to_node(int destination, vector1< double > const &message)
Definition: SimulateMPI.cc:364