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