MOAB: Mesh Oriented datABase  (version 5.2.1)
IODebugTrack.cpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines