Branch data Line data Source code
1 : : #include "IODebugTrack.hpp"
2 : : #include "moab/Range.hpp"
3 : : #include <iostream>
4 : : #include <vector>
5 : : #include <assert.h>
6 : :
7 : : #ifdef MOAB_HAVE_MPI
8 : : #include "moab_mpi.h"
9 : : #endif
10 : :
11 : : const char PFX[] = ">>> ";
12 : :
13 : : namespace moab
14 : : {
15 : :
16 : 0 : IODebugTrack::IODebugTrack( bool enabled, const std::string& name, std::ostream& output_stream,
17 : : unsigned long table_size )
18 [ # # ]: 0 : : enableOutput( enabled ), tableName( name ), ostr( output_stream ), maxSize( table_size ), haveMPI( false )
19 : : {
20 : : #ifdef MOAB_HAVE_MPI
21 [ # # ]: 0 : MPI_Comm_rank( MPI_COMM_WORLD, &mpiRank );
22 : : #else
23 : : mpiRank = 0;
24 : : #endif
25 : 0 : }
26 : :
27 : 565 : IODebugTrack::IODebugTrack( bool enabled, const std::string& name, unsigned long table_size )
28 [ + - ]: 565 : : enableOutput( enabled ), tableName( name ), ostr( std::cerr ), maxSize( table_size )
29 : : {
30 : 565 : mpiRank = 0;
31 : 565 : haveMPI = false;
32 : : #ifdef MOAB_HAVE_MPI
33 : 565 : int have_init = 0;
34 [ + - ]: 565 : MPI_Initialized( &have_init );
35 [ + + ]: 565 : if( have_init )
36 : : {
37 : 284 : haveMPI = true;
38 [ + - ]: 284 : MPI_Comm_rank( MPI_COMM_WORLD, &mpiRank );
39 : : }
40 : : #endif
41 : 565 : }
42 : :
43 [ - + ][ - + ]: 1130 : IODebugTrack::~IODebugTrack()
44 : : {
45 [ - + ][ # # ]: 565 : if( !enableOutput || mpiRank ) // only root prints gap summary
46 : : return;
47 : :
48 [ # # ]: 0 : if( dataSet.empty() )
49 : : {
50 : 0 : ostr << PFX << tableName << " : No Data Written!!!!" << std::endl;
51 : 565 : return;
52 : : }
53 : :
54 : 0 : std::list< DRange >::const_iterator i;
55 [ # # ]: 0 : if( !maxSize )
56 : : {
57 [ # # ]: 0 : for( i = dataSet.begin(); i != dataSet.end(); ++i )
58 [ # # ]: 0 : if( i->end >= maxSize ) maxSize = i->end + 1;
59 : : }
60 : 0 : Range processed;
61 : 0 : Range::iterator h = processed.begin();
62 : 0 : bool wrote_zero = false;
63 [ # # ]: 0 : for( i = dataSet.begin(); i != dataSet.end(); ++i )
64 : : {
65 : : // ranges cannot contain zero
66 [ # # ]: 0 : assert( i->begin <= i->end );
67 [ # # ]: 0 : if( i->begin )
68 : 0 : h = processed.insert( h, i->begin, i->end );
69 : : else
70 : : {
71 : 0 : wrote_zero = true;
72 [ # # ]: 0 : if( i->end ) h = processed.insert( h, i->begin + 1, i->end );
73 : : }
74 : : }
75 : :
76 : : // ranges cannot contain zero
77 [ # # ]: 0 : Range unprocessed;
78 [ # # ]: 0 : if( maxSize > 1 ) unprocessed.insert( 1, maxSize - 1 );
79 : 0 : unprocessed = subtract( unprocessed, processed );
80 [ # # ]: 0 : if( unprocessed.empty() ) return;
81 : :
82 : 0 : Range::const_pair_iterator j;
83 [ # # ][ # # ]: 0 : for( j = unprocessed.const_pair_begin(); j != unprocessed.const_pair_end(); ++j )
84 : : {
85 : 0 : unsigned long b = j->first;
86 : 0 : unsigned long e = j->second;
87 [ # # ][ # # ]: 0 : if( b == 1 && !wrote_zero ) b = 0;
88 : :
89 : 0 : ostr << PFX << tableName << " : range not read/written: [" << b << "," << e << "]" << std::endl;
90 : 0 : ostr.flush();
91 : 0 : }
92 : 0 : }
93 : :
94 : 563 : void IODebugTrack::record_io( unsigned long begin, unsigned long count )
95 : : {
96 [ - + ][ # # ]: 563 : if( enableOutput && count )
97 : : {
98 : 0 : DRange ins = { begin, begin + count - 1, static_cast< long unsigned >( mpiRank ) };
99 [ # # ]: 0 : record_io( ins );
100 : : }
101 : 563 : }
102 : :
103 : 0 : void IODebugTrack::record_io( DRange ins )
104 : : {
105 [ # # ]: 0 : if( !enableOutput ) return;
106 : :
107 : : // only root should get non-local data
108 [ # # ][ # # ]: 0 : assert( !mpiRank || ins.rank == (unsigned)mpiRank );
109 [ # # ]: 0 : assert( ins.begin <= ins.end );
110 : :
111 : : // test for out-of-bounds write
112 [ # # ][ # # ]: 0 : if( maxSize && ins.end >= maxSize )
113 [ # # ][ # # ]: 0 : ostr << ": Out of bounds write on rank " << mpiRank << ": [" << ins.begin << "," << ins.end
[ # # ][ # # ]
[ # # ][ # # ]
114 [ # # ][ # # ]: 0 : << "] >= " << maxSize << std::endl;
[ # # ]
115 : :
116 : : // test for overlap with all existing ranges
117 [ # # ]: 0 : std::list< DRange >::iterator i;
118 [ # # ][ # # ]: 0 : for( i = dataSet.begin(); i != dataSet.end(); ++i )
[ # # ]
119 : : {
120 [ # # ][ # # ]: 0 : if( i->end >= ins.begin && i->begin <= ins.end )
[ # # ][ # # ]
[ # # ]
121 : : { // if overlap
122 [ # # ][ # # ]: 0 : ostr << PFX << tableName;
123 [ # # ][ # # ]: 0 : if( i->rank == ins.rank )
124 : : {
125 [ # # ][ # # ]: 0 : if( mpiRank == (int)ins.rank ) ostr << ": Local overwrite on rank " << mpiRank;
[ # # ]
126 : :
127 : : // otherwise should have been logged on remote proc, do nothing here
128 : : }
129 : : else
130 [ # # ][ # # ]: 0 : ostr << ": Conflicting write for ranks " << i->rank << " and " << ins.rank;
[ # # ][ # # ]
[ # # ]
131 : :
132 [ # # ][ # # ]: 0 : ostr << ": [" << i->begin << "," << i->end << "] and [" << ins.begin << "," << ins.end << "]" << std::endl;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
133 [ # # ]: 0 : ostr.flush();
134 : : }
135 : : }
136 : :
137 [ # # ]: 0 : dataSet.push_back( ins );
138 : : }
139 : :
140 : 660 : void IODebugTrack::all_reduce()
141 : : {
142 : : #ifdef MOAB_HAVE_MPI
143 [ - + ][ # # ]: 660 : if( !enableOutput || !haveMPI ) return;
144 : :
145 : : int commsize;
146 [ # # ]: 0 : MPI_Comm_size( MPI_COMM_WORLD, &commsize );
147 : 0 : int count = 3 * dataSet.size();
148 [ # # ][ # # ]: 0 : std::vector< int > displs( commsize ), counts( commsize );
149 [ # # ][ # # ]: 0 : MPI_Gather( &count, 1, MPI_INT, &counts[0], 1, MPI_INT, 0, MPI_COMM_WORLD );
150 [ # # ]: 0 : displs[0] = 0;
151 [ # # ]: 0 : for( int i = 1; i < commsize; ++i )
152 [ # # ][ # # ]: 0 : displs[i] = displs[i - 1] + counts[i - 1];
[ # # ]
153 [ # # ][ # # ]: 0 : int total = ( displs.back() + counts.back() ) / 3;
154 : 0 : count /= 3;
155 : :
156 [ # # ][ # # ]: 0 : std::vector< DRange > send( dataSet.size() ), recv( total );
157 [ # # ]: 0 : std::copy( dataSet.begin(), dataSet.end(), send.begin() );
158 [ # # ][ # # ]: 0 : MPI_Gatherv( (void*)&send[0], 3 * send.size(), MPI_UNSIGNED_LONG, (void*)&recv[0], &counts[0], &displs[0],
[ # # ][ # # ]
159 [ # # ]: 0 : MPI_UNSIGNED_LONG, 0, MPI_COMM_WORLD );
160 : :
161 [ # # ]: 0 : if( 0 == mpiRank )
162 : : {
163 [ # # ]: 0 : for( int i = count; i < total; ++i )
164 [ # # ][ # # ]: 0 : record_io( recv[i] );
165 : : }
166 : : else
167 : : {
168 : 0 : dataSet.clear();
169 : 0 : }
170 : : #endif
171 : : }
172 : :
173 [ + - ][ + - ]: 228 : } // namespace moab
|