MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 #include "IODebugTrack.hpp" 00002 #include "moab/Range.hpp" 00003 #include <iostream> 00004 #include <vector> 00005 #include <cassert> 00006 00007 #ifdef MOAB_HAVE_MPI 00008 #include "moab_mpi.h" 00009 #endif 00010 00011 const char PFX[] = ">>> "; 00012 00013 namespace moab 00014 { 00015 00016 IODebugTrack::IODebugTrack( bool enabled, 00017 const std::string& name, 00018 std::ostream& output_stream, 00019 unsigned long table_size ) 00020 : enableOutput( enabled ), tableName( name ), ostr( output_stream ), maxSize( table_size ), haveMPI( false ) 00021 { 00022 #ifdef MOAB_HAVE_MPI 00023 MPI_Comm_rank( MPI_COMM_WORLD, &mpiRank ); 00024 #else 00025 mpiRank = 0; 00026 #endif 00027 } 00028 00029 IODebugTrack::IODebugTrack( bool enabled, const std::string& name, unsigned long table_size ) 00030 : enableOutput( enabled ), tableName( name ), ostr( std::cerr ), maxSize( table_size ) 00031 { 00032 mpiRank = 0; 00033 haveMPI = false; 00034 #ifdef MOAB_HAVE_MPI 00035 int have_init = 0; 00036 MPI_Initialized( &have_init ); 00037 if( have_init ) 00038 { 00039 haveMPI = true; 00040 MPI_Comm_rank( MPI_COMM_WORLD, &mpiRank ); 00041 } 00042 #endif 00043 } 00044 00045 IODebugTrack::~IODebugTrack() 00046 { 00047 if( !enableOutput || mpiRank ) // only root prints gap summary 00048 return; 00049 00050 if( dataSet.empty() ) 00051 { 00052 ostr << PFX << tableName << " : No Data Written!!!!" << std::endl; 00053 return; 00054 } 00055 00056 std::list< DRange >::const_iterator i; 00057 if( !maxSize ) 00058 { 00059 for( i = dataSet.begin(); i != dataSet.end(); ++i ) 00060 if( i->end >= maxSize ) maxSize = i->end + 1; 00061 } 00062 Range processed; 00063 Range::iterator h = processed.begin(); 00064 bool wrote_zero = false; 00065 for( i = dataSet.begin(); i != dataSet.end(); ++i ) 00066 { 00067 // ranges cannot contain zero 00068 assert( i->begin <= i->end ); 00069 if( i->begin ) 00070 h = processed.insert( h, i->begin, i->end ); 00071 else 00072 { 00073 wrote_zero = true; 00074 if( i->end ) h = processed.insert( h, i->begin + 1, i->end ); 00075 } 00076 } 00077 00078 // ranges cannot contain zero 00079 Range unprocessed; 00080 if( maxSize > 1 ) unprocessed.insert( 1, maxSize - 1 ); 00081 unprocessed = subtract( unprocessed, processed ); 00082 if( unprocessed.empty() ) return; 00083 00084 Range::const_pair_iterator j; 00085 for( j = unprocessed.const_pair_begin(); j != unprocessed.const_pair_end(); ++j ) 00086 { 00087 unsigned long b = j->first; 00088 unsigned long e = j->second; 00089 if( b == 1 && !wrote_zero ) b = 0; 00090 00091 ostr << PFX << tableName << " : range not read/written: [" << b << "," << e << "]" << std::endl; 00092 ostr.flush(); 00093 } 00094 } 00095 00096 void IODebugTrack::record_io( unsigned long begin, unsigned long count ) 00097 { 00098 if( enableOutput && count ) 00099 { 00100 DRange ins = { begin, begin + count - 1, static_cast< long unsigned >( mpiRank ) }; 00101 record_io( ins ); 00102 } 00103 } 00104 00105 void IODebugTrack::record_io( DRange ins ) 00106 { 00107 if( !enableOutput ) return; 00108 00109 // only root should get non-local data 00110 assert( !mpiRank || ins.rank == (unsigned)mpiRank ); 00111 assert( ins.begin <= ins.end ); 00112 00113 // test for out-of-bounds write 00114 if( maxSize && ins.end >= maxSize ) 00115 ostr << ": Out of bounds write on rank " << mpiRank << ": [" << ins.begin << "," << ins.end 00116 << "] >= " << maxSize << std::endl; 00117 00118 // test for overlap with all existing ranges 00119 std::list< DRange >::iterator i; 00120 for( i = dataSet.begin(); i != dataSet.end(); ++i ) 00121 { 00122 if( i->end >= ins.begin && i->begin <= ins.end ) 00123 { // if overlap 00124 ostr << PFX << tableName; 00125 if( i->rank == ins.rank ) 00126 { 00127 if( mpiRank == (int)ins.rank ) ostr << ": Local overwrite on rank " << mpiRank; 00128 00129 // otherwise should have been logged on remote proc, do nothing here 00130 } 00131 else 00132 ostr << ": Conflicting write for ranks " << i->rank << " and " << ins.rank; 00133 00134 ostr << ": [" << i->begin << "," << i->end << "] and [" << ins.begin << "," << ins.end << "]" << std::endl; 00135 ostr.flush(); 00136 } 00137 } 00138 00139 dataSet.push_back( ins ); 00140 } 00141 00142 void IODebugTrack::all_reduce() 00143 { 00144 #ifdef MOAB_HAVE_MPI 00145 if( !enableOutput || !haveMPI ) return; 00146 00147 int commsize; 00148 MPI_Comm_size( MPI_COMM_WORLD, &commsize ); 00149 int count = 3 * dataSet.size(); 00150 std::vector< int > displs( commsize ), counts( commsize ); 00151 MPI_Gather( &count, 1, MPI_INT, &counts[0], 1, MPI_INT, 0, MPI_COMM_WORLD ); 00152 displs[0] = 0; 00153 for( int i = 1; i < commsize; ++i ) 00154 displs[i] = displs[i - 1] + counts[i - 1]; 00155 int total = ( displs.back() + counts.back() ) / 3; 00156 count /= 3; 00157 00158 std::vector< DRange > send( dataSet.size() ), recv( total ); 00159 std::copy( dataSet.begin(), dataSet.end(), send.begin() ); 00160 MPI_Gatherv( (void*)&send[0], 3 * send.size(), MPI_UNSIGNED_LONG, (void*)&recv[0], &counts[0], &displs[0], 00161 MPI_UNSIGNED_LONG, 0, MPI_COMM_WORLD ); 00162 00163 if( 0 == mpiRank ) 00164 { 00165 for( int i = count; i < total; ++i ) 00166 record_io( recv[i] ); 00167 } 00168 else 00169 { 00170 dataSet.clear(); 00171 } 00172 #endif 00173 } 00174 00175 } // namespace moab