Mesh Oriented datABase  (version 5.4.1)
Array-based unstructured mesh datastructure
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 <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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines