14 #define TRDEBUG TR.Debug
21 #include <utility/assert.hh>
33 #include <basic/Tracer.hh>
39 #include <basic/options/option.hh>
40 #include <basic/options/keys/wum.OptionKeys.gen.hh>
42 #include <numeric/random/random.hh>
43 #include <ObjexxFCL/string.functions.hh>
44 #include <ObjexxFCL/format.hh>
46 #include <utility/vector1.hh>
50 #if defined(WIN32) || defined(__CYGWIN__)
54 using namespace ObjexxFCL::fmt;
59 static basic::Tracer
TR(
"MPI_WUM");
60 static numeric::random::RandomGenerator
RG(23765);
65 MPI_Comm_rank( MPI_COMM_WORLD, (
int* )( &mpi_rank_ ) );
67 utility_exit_with_message(
"ERROR: The MPI_WorkUnitManager will not work unless you have compiled using extras=mpi" );
75 MPI_Comm_size( MPI_COMM_WORLD, (
int* )( &mpi_npes_ ) );
77 utility_exit_with_message(
"ERROR: The MPI_WorkUnitManager will not work unless you have compiled using extras=mpi" );
99 MPI_WorkUnitManager::MPI_WorkUnitManager(
char machine_letter ):
102 traffic_total_received_(0),
103 traffic_total_sent_(0),
108 machine_letter_( machine_letter )
110 TR <<
"Starting MPI_WorkUnitManager.." << std::endl;
111 using namespace basic::options;
112 using namespace basic::options::OptionKeys;
120 TR <<
"This is node " <<
mpi_rank() <<
" Nprocs: " <<
mpi_npes() << std::endl;
146 TR.Trace <<
"Probing for incoming messages .." << std::endl;
150 TR.Trace <<
"Fulfilling work requests since we have outbound work" << std::endl;
158 TR.Error <<
"ERROR: status.MPI_TAG != WUM_MPI_REQUEST_WU" << std::endl;
161 TR.Trace <<
"Someone requested work!" << std::endl;
166 TR.Trace <<
"Present " << (before_size -
outbound().
size()) <<
" units" << std::endl;
169 TR.Trace <<
"Now listening for any inbound work" << std::endl;
170 MPI_Iprobe(
MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &result, &status);
172 if( !wait_until_message ){
183 switch( status.MPI_TAG ){
185 TR.Debug <<
"Sending WU on request to " << status.MPI_SOURCE << std::endl;
189 TR.Debug <<
"Receiving WU from " << status.MPI_SOURCE << std::endl;
193 TR.Error <<
"Unknown MPI_Message waiting from" << status.MPI_SOURCE <<
" with tag " << status.MPI_TAG << std::endl;
217 const core::Real warning_threshold = 0.050000;
219 runtime_assert( dest_rank <
mpi_npes() );
220 runtime_assert( (
int)dest_rank !=
mpi_rank() );
224 int size_of_raw_data;
225 unsigned char * raw_data_ptr=NULL;
226 size_of_raw_data = wu->raw_data_dump( &raw_data_ptr );
232 TRDEBUG <<
"Sending workunit to " << dest_rank << std::endl;
235 MPI_Ssend( &size_of_raw_data, 1, MPI_UNSIGNED, dest_rank,
WUM_MPI_SEND_WU, MPI_COMM_WORLD );
236 TR.Debug <<
"Sent header announcing incoming WU of size " << F(5,1,(size_of_raw_data/1024.0)) <<
"kB" <<
" to node " << dest_rank << std::endl;
239 TR.Debug <<
"Sending WU" << std::endl;
240 MPI_Ssend( (
char*) raw_data_ptr, size_of_raw_data, MPI_CHAR, dest_rank,
WUM_MPI_DATA_BLOCK, MPI_COMM_WORLD );
241 TR.Debug <<
"WU sent" << std::endl;
246 TRDEBUG <<
"MPI_SEND: " << dest_rank <<
" " << F(7,1,(start_send - start_wait)*1000.0) <<
"ms " << F(7,1,(end_send - start_send)*1000.0)
247 <<
"ms " << F(5,1,(size_of_raw_data/1024.0)) <<
"kB" << std::endl;
248 if( (end_send - start_wait) > warning_threshold){
249 TR <<
"WARNING LONG MPI_SEND: " << dest_rank <<
" " << F(7,1,(start_send - start_wait)*1000.0) <<
"ms " << F(7,1,(end_send - start_send)*1000.0)
250 <<
"ms " << F(5,1,(size_of_raw_data/1024.0)) <<
"kB" << std::endl;
253 delete [] raw_data_ptr;
254 TR.Trace <<
" Delete temp data.. " << std::endl;
256 wu->clear_serial_data();
266 int size_of_raw_data;
267 unsigned char * raw_data_ptr;
272 TR.Debug <<
"Receiving MPI header (ie how big the WU will be)" << std::endl;
273 MPI_Recv( &size_of_raw_data, 1, MPI_UNSIGNED, node_rank,
WUM_MPI_SEND_WU, MPI_COMM_WORLD, &status);
274 TR.Debug <<
"Received MPI header, receiving WU of " << F(5,1,(size_of_raw_data/1024.0)) <<
"kB from node " << status.MPI_SOURCE << std::endl;
275 raw_data_ptr =
new unsigned char [size_of_raw_data];
277 TRDEBUG <<
"Confirmed datablock is coming" << std::endl;
278 MPI_Recv( (
char*) raw_data_ptr, size_of_raw_data, MPI_CHAR, status.MPI_SOURCE,
WUM_MPI_DATA_BLOCK, MPI_COMM_WORLD, &status);
280 TRDEBUG <<
"MPI_RECV: " << status.MPI_SOURCE << F(5,0,(end_recv - start_recv)/1000000.0) <<
"us " << F(5,1,(size_of_raw_data/1024.0)) <<
"kB" << std::endl;
286 if( raw_data_ptr[size_of_raw_data-1] != 0){
287 TR.Error <<
" ERROR: cannot load data - terminal zero not found!" << std::endl;
291 raw_data_ptr[size_of_raw_data-1] = 0;
295 TRDEBUG <<
" RECEVIED WU: Data: " << std::endl;
298 runtime_assert( wu );
299 wu->raw_data_load( raw_data_ptr, size_of_raw_data );
300 delete [] raw_data_ptr;
309 runtime_assert( qualified_wu );
311 (*qualified_wu) = (*wu);
312 (*qualified_wu).last_received_from_ = status.MPI_SOURCE;
313 TRDEBUG <<
" Received: " << std::endl;
316 qualified_wu->deserialize( );
317 qualified_wu->clear_serial_data();
319 TRDEBUG <<
"DONE Receiving" << std::endl;
336 for( ; suitable_work_unit !=
outbound().
end(); ++suitable_work_unit )
339 if( !( (*suitable_work_unit)->in_blacklist( status.MPI_SOURCE ) ) )
break;
341 TRDEBUG <<
"WU " << (*suitable_work_unit)->id() <<
" was not sent to " << status.MPI_SOURCE <<
" because it was blacklisted." << std::endl;
346 TRDEBUG <<
"No suitable work for node " << status.MPI_SOURCE <<
" ( blacklisted=" <<
outbound().
size() <<
")" << std::endl;
350 wait_wu->set_wu_type(
"waitwu");
357 --suitable_work_unit;
363 TRDEBUG <<
"Sending next WU on request... "<< std::endl;
373 TRDEBUG <<
"END Send-on-request" << std::endl;
427 I( (
int)7, total_secs ) <<
"s " <<
428 F( 4, 1, 100.0f*( timing_total_[
TIMING_CPU] / total_secs)) <<
"% " <<
431 F( 4, 1, 100.0f*( timing_total_[
TIMING_IO_READ] / total_secs)) <<
"% " <<
432 F( 4, 1, 100.0f*( timing_total_[
TIMING_IO_WRITE] / total_secs)) <<
"% " <<
433 F( 4, 1, 100.0f*( timing_total_[
TIMING_WAIT] / total_secs)) <<
"% " <<
434 F( 4, 1, 100.0f*( timing_total_[
TIMING_IDLE] / total_secs)) <<
"% " <<
447 inbound().
mem_stats( in_total_structs, in_total_structs_memory, in_total_WU_memory );
453 outbound().
mem_stats( out_total_structs, out_total_structs_memory, out_total_WU_memory );
456 "IWUs: " << in_total <<
" " <<
457 "IStruc: " << in_total_structs <<
" " <<
458 "IMem: " <<
int((in_total_WU_memory + in_total_structs_memory)/1000.0) <<
" " <<
459 "OWUs: " << out_total <<
" " <<
460 "OStruc: " << out_total_structs <<
" " <<
461 "OMem: " <<
int((out_total_WU_memory+out_total_structs_memory)/1000.0) <<
" " <<